# Module `netapp_ontap.resources.software`

Copyright © 2023 NetApp Inc. All rights reserved.

This file has been automatically generated based on the ONTAP REST API documentation.

## Overview

You can use the ONTAP cluster software API to retrieve and display relevant information about a software profile, software packages collection, software history collection, and firmware packages collection. This API retrieves the information about all software packages present in the cluster, or a specific software package, or firmware upgrade status.
You can use the POST request to download a software package/firmware from an HTTP or FTP server. The PATCH request provides the option to upgrade the cluster software version. Select the `validate_only` field to validate the package before triggering the update. Set the `version` field to trigger the installation of the package in the cluster. You can pause, resume, or cancel any ongoing software upgrade by selecting `action`. You can use the DELETE request to remove a specific software package present in the cluster.

## Examples

### Retrieving software profile information

The following example shows how to retrieve software and firmware profile information. You can check the validation results after selecting the `validate_only` field. Upgrade progress information is available after an upgrade has started.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.get(return_timeout=15)
        print(resource)

Try it out

    Software(
        {
            "status_details": [
                {
                    "state": "completed",
                    "end_time": "2018-05-21T11:53:04+05:30",
                    "issue": {"code": 0, "message": "Image update complete"},
                    "node": {"name": "sti70-vsim-ucs165n"},
                    "start_time": "2018-05-21T09:53:04+05:30",
                    "name": "do-download-job",
                }
            ],
            "state": "in_progress",
            "validation_results": [
                {
                    "action": {"message": "Use NFS hard mounts, if possible."},
                    "issue": {"message": "Use NFS hard mounts, if possible."},
                    "status": "warning",
                    "update_check": "NFS mounts",
                }
            ],
            "pending_version": "9.6.0",
            "_links": {"self": {"href": "/api/cluster/software/"}},
            "metrocluster": {
                "progress_details": {
                    "message": 'Installing software image on cluster "sti70-vsim-ucs165n_siteA".'
                },
                "progress_summary": {"message": "Update paused by user"},
                "clusters": [
                    {
                        "name": "sti70-vsim-ucs165n_siteA",
                        "elapsed_duration": 0,
                        "state": "waiting",
                        "estimated_duration": 3480,
                    }
                ],
            },
            "version": "9.5.0",
            "nodes": [
                {
                    "firmware": {
                        "dqp": {
                            "revision": "20200117",
                            "version": "3.17",
                            "record_count": {
                                "device": 29,
                                "alias": 200,
                                "system": 3,
                                "drive": 680,
                            },
                            "file_name": "qual_devices_v2",
                        },
                        "shelf": {"update_status": "idle", "in_progress_count": 2},
                        "cluster_fw_progress": [
                            {
                                "update_type": "automatic_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "abc.zip",
                            },
                            {
                                "update_type": "manual_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "xyz.zip",
                            },
                        ],
                        "disk": {
                            "update_status": "idle",
                            "average_duration_per_disk": 120,
                            "total_completion_estimate": 0,
                            "num_waiting_download": 0,
                        },
                        "sp_bmc": {
                            "image": " primary",
                            "end_time": "2018-05-21T09:53:04+05:30",
                            "running_version": "1.2.3.4",
                            "is_current": True,
                            "in_progress": False,
                            "percent_done": 100,
                            "fw_type": "SP",
                            "start_time": "2018-05-21T09:53:04+05:30",
                        },
                    },
                    "version": "9.5.0",
                }
            ],
            "update_details": [
                {
                    "elapsed_duration": 29,
                    "state": "in_progress",
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                    "node": {"name": "sti70-vsim-ucs165n"},
                }
            ],
        }
    )

### Upgrading the software version

The following example shows how to upgrade cluster software. Set the `version` field to trigger the installation of the package. You can select the `validate_only` field to validate the package before the installation starts. Setting `skip_warning` as `true` ignores the validation warning before the installation starts. Setting the `action` field performs a `pause`, `resume`, or `cancel' operation on an ongoing upgrade. An upgrade can only be resumed if it is in the paused state. Setting`stabilize_minutes`allows each node a specified amount of time to stabilize after a reboot; the default is 8 minutes. If`show_validation_details` is set to "true", all validation details will be shown in the output.
You can start the upgrade process at the cluster level. There are no options available to start the upgrade for a specific node or HA pair.

#### 1. Validating the package and verifying the validation results

The following example shows how to validate a cluster software package. You must validate the package before the software upgrade. Set the `validate_only` field to `true` to start the validation. You can check for validation results in the GET /cluster/software endpoint.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt_ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.version = "9.5.0"
        resource.patch(hydrate=True, validate_only=True)

The call to validate the software cluster version returns the job UUID, including a HAL link to retrieve details about the job. The job object includes a `state` field and a message to indicate the progress of the job. When the job is complete and the application is fully created, the message indicates success and the `state` field of the job is set to `success`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Job

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Job(uuid="f587d316-5feb-11e8-b0e0-005056956dfc")
        resource.get()
        print(resource)

Try it out

    Job(
        {
            "message": "success",
            "state": "success",
            "code": 0,
            "uuid": "f587d316-5feb-11e8-b0e0-005056956dfc",
            "_links": {
                "self": {"href": "/api/cluster/jobs/f587d316-5feb-11e8-b0e0-005056956dfc"}
            },
            "description": "PATCH /api/cluster/software",
        }
    )

You can check for validation results in the GET /cluster/software endpoint. The following example shows how to check the validation warnings and errors after setting the `validate_only` field to `true`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.get()
        print(resource)

Try it out

    Software(
        {
            "elapsed_duration": 56,
            "state": "failed",
            "validation_results": [
                {
                    "action": {
                        "message": "Check cluster HA configuration. Check storage failover status."
                    },
                    "issue": {
                        "message": 'Cluster HA is not configured in the cluster. Storage failover is not enabled on node "node1", "node2".'
                    },
                    "status": "error",
                    "update_check": "High Availability status",
                },
                {
                    "action": {
                        "message": 'Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update.'
                    },
                    "issue": {
                        "message": 'Manual validation checks need to be performed. Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update. Failing to do so can result in an update failure or an I/O disruption.'
                    },
                    "status": "warning",
                    "update_check": "Manual checks",
                },
            ],
            "estimated_duration": 600,
            "_links": {"self": {"href": "/api/cluster/software"}},
            "version": "9.7.0",
            "nodes": [
                {
                    "firmware": {
                        "dqp": {
                            "revision": "20200117",
                            "version": "3.17",
                            "record_count": {
                                "device": 29,
                                "alias": 200,
                                "system": 3,
                                "drive": 680,
                            },
                            "file_name": "qual_devices_v2",
                        },
                        "shelf": {"update_status": "idle", "in_progress_count": 2},
                        "cluster_fw_progress": [
                            {
                                "update_type": "automatic_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "abc.zip",
                            },
                            {
                                "update_type": "automatic_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "xyz.zip",
                            },
                        ],
                        "disk": {
                            "update_status": "idle",
                            "average_duration_per_disk": 120,
                            "total_completion_estimate": 0,
                            "num_waiting_download": 0,
                        },
                        "sp_bmc": {
                            "image": " primary",
                            "end_time": "2018-05-21T09:53:04+05:30",
                            "running_version": "1.2.3.4",
                            "is_current": True,
                            "in_progress": False,
                            "percent_done": 100,
                            "fw_type": "SP",
                            "start_time": "2018-05-21T09:53:04+05:30",
                        },
                    },
                    "version": "9.5.0",
                }
            ],
        }
    )

#### 2. Updating the cluster

The following example shows how to initiate a cluster software upgrade. You must validate the package before the software upgrade starts. Set the `skip_warnings` field to `true` to skip validation warnings and start the software package upgrade. You can specify the `stabilize_minutes` value between 1 to 60 minutes. Setting `stabilize_minutes` allows each node a specified amount of time to stabilize after a reboot; the default is 8 minutes. If the value of `show_validation_details` is set to "true", then all validation details will be shown in the output.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt_ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.version = "9.5.0"
        resource.patch(hydrate=True, skip_warnings=True)

The call to update the software cluster version returns the job UUID, including a HAL link to retrieve details about the job. The job object includes a `state` field and a message to indicate the progress of the job. When the job is complete and the application is fully created, the message indicates success and the `state` field of the job is set to `success`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Job

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Job(uuid="f587d316-5feb-11e8-b0e0-005056956dfc")
        resource.get()
        print(resource)

Try it out

    Job(
        {
            "message": "success",
            "state": "success",
            "code": 0,
            "uuid": "f587d316-5feb-11e8-b0e0-005056956dfc",
            "_links": {
                "self": {"href": "/api/cluster/jobs/f587d316-5feb-11e8-b0e0-005056956dfc"}
            },
            "description": "PATCH /api/cluster/software",
        }
    )

You can check the update progress information in the GET /cluster/software endpoint. The following example shows how to check the progress of an update after setting the `skip_warnings` field to `true`. Each node's object also includes information about the firmware update status on the node.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.get()
        print(resource)

Try it out

    Software(
        {
            "status_details": [
                {
                    "end_time": "2019-01-14T23:12:14+05:30",
                    "issue": {"code": 10551400, "message": "Installing software image."},
                    "node": {"name": "node1"},
                    "start_time": "2019-01-14T23:12:14+05:30",
                    "name": "do-download-job",
                },
                {
                    "end_time": "2019-01-14T23:12:14+05:30",
                    "issue": {"code": 10551400, "message": "Installing software image."},
                    "node": {"name": "node2"},
                    "start_time": "2019-01-14T23:12:14+05:30",
                    "name": "do-download-job",
                },
            ],
            "elapsed_duration": 63,
            "state": "in_progress",
            "validation_results": [
                {
                    "action": {
                        "message": 'Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update.'
                    },
                    "issue": {
                        "message": 'Manual validation checks need to be performed. Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update. Failing to do so can result in an update failure or an I/O disruption.'
                    },
                    "status": "warning",
                    "update_check": "Manual checks",
                }
            ],
            "pending_version": "9.7.0",
            "estimated_duration": 5220,
            "_links": {"self": {"href": "/api/cluster/software"}},
            "version": "9.7.0",
            "nodes": [
                {
                    "firmware": {
                        "dqp": {
                            "revision": "20200117",
                            "version": "3.17",
                            "record_count": {
                                "device": 29,
                                "alias": 200,
                                "system": 3,
                                "drive": 680,
                            },
                            "file_name": "qual_devices_v2",
                        },
                        "shelf": {"update_status": "idle", "in_progress_count": 2},
                        "cluster_fw_progress": [
                            {
                                "update_type": "automated_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 3",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3498",
                                            "name": "Node 4",
                                        },
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "abc.zip",
                            },
                            {
                                "update_type": "automated_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "xyz.zip",
                            },
                        ],
                        "disk": {
                            "update_status": "idle",
                            "average_duration_per_disk": 120,
                            "total_completion_estimate": 0,
                            "num_waiting_download": 0,
                        },
                        "sp_bmc": {
                            "image": " primary",
                            "end_time": "2018-05-21T09:53:04+05:30",
                            "running_version": "1.2.3.4",
                            "is_current": True,
                            "in_progress": False,
                            "percent_done": 100,
                            "fw_type": "SP",
                            "start_time": "2018-05-21T09:53:04+05:30",
                        },
                    },
                    "version": "9.5.0",
                }
            ],
            "update_details": [
                {
                    "elapsed_duration": 10,
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                    "node": {"name": "node1"},
                },
                {
                    "elapsed_duration": 10,
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                    "node": {"name": "node2"},
                },
            ],
        }
    )

In the case of a post update check failure, the details are available under the heading "post_update_checks" in the GET /cluster/software endpoint. The following example shows how to check the progress of an update after a post update check has failed. Each node's object also includes information about the firmware update status on the node.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.get()
        print(resource)

Try it out

    Software(
        {
            "status_details": [
                {
                    "end_time": "2019-01-14T23:12:14+05:30",
                    "issue": {"code": 0, "message": "Image update complete."},
                    "node": {"name": "node1"},
                    "start_time": "2019-01-14T23:12:14+05:30",
                    "name": "do-download-job",
                },
                {
                    "end_time": "2019-01-14T23:12:14+05:30",
                    "issue": {"code": 0, "message": "Image update complete."},
                    "node": {"name": "node2"},
                    "start_time": "2019-01-14T23:12:14+05:30",
                    "name": "do-download-job",
                },
            ],
            "elapsed_duration": 63,
            "state": "in_progress",
            "validation_results": [
                {
                    "action": {
                        "message": 'Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update.'
                    },
                    "issue": {
                        "message": 'Manual validation checks need to be performed. Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update. Failing to do so can result in an update failure or an I/O disruption.'
                    },
                    "status": "warning",
                    "update_check": "Manual checks",
                }
            ],
            "pending_version": "9.7.0",
            "estimated_duration": 5220,
            "post_update_checks": [
                {
                    "action": {"message": "Ensure all aggregates are online."},
                    "issue": {"message": "Not all aggregates are online"},
                    "status": "error",
                    "update_check": "Aggregate Health Status",
                },
                {
                    "action": {
                        "message": "Ensure storage failover is enabled on all nodes of the cluster."
                    },
                    "issue": {
                        "message": "Storage failover is not enabled on nodes of the cluster."
                    },
                    "status": "error",
                    "update_check": "HA Health Status",
                },
            ],
            "_links": {"self": {"href": "/api/cluster/software"}},
            "version": "9.7.0",
            "nodes": [
                {
                    "firmware": {
                        "dqp": {
                            "revision": "20200117",
                            "version": "3.17",
                            "record_count": {
                                "device": 29,
                                "alias": 200,
                                "system": 3,
                                "drive": 680,
                            },
                            "file_name": "qual_devices_v2",
                        },
                        "shelf": {"update_status": "idle", "in_progress_count": 2},
                        "cluster_fw_progress": [
                            {
                                "update_type": "automated_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "<message catalog text>",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 3,
                                        "status": "working",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Error message",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "completed",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "abc.zip",
                            },
                            {
                                "update_type": "automated_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Error message",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 0,
                                        "status": "completed",
                                        "attempts": 1,
                                    },
                                    {
                                        "message": "Error message",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 2",
                                        },
                                        "code": 0,
                                        "status": "completed",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "xyz.zip",
                            },
                        ],
                        "disk": {
                            "update_status": "idle",
                            "average_duration_per_disk": 120,
                            "total_completion_estimate": 0,
                            "num_waiting_download": 0,
                        },
                        "sp_bmc": {
                            "image": " primary",
                            "end_time": "2018-05-21T09:53:04+05:30",
                            "running_version": "1.2.3.4",
                            "is_current": True,
                            "in_progress": True,
                            "percent_done": 100,
                            "fw_type": "SP",
                            "start_time": "2018-05-21T09:53:04+05:30",
                        },
                    },
                    "version": "9.5.0",
                }
            ],
            "update_details": [
                {
                    "elapsed_duration": 3120,
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                    "node": {"name": "node1"},
                },
                {
                    "elapsed_duration": 3210,
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                    "node": {"name": "node2"},
                },
                {
                    "elapsed_duration": 10,
                    "phase": "Post-update checks",
                    "estimated_duration": 600,
                    "node": {"name": "node2"},
                },
            ],
        }
    )

#### 3. Pausing, resuming or canceling an upgrade

The following example shows how to `pause` an ongoing cluster software package upgrade. Set the `action` field to `pause`, `resume`, or `cancel` to pause, resume or cancel the upgrade respectively. Not all update operations support these actions. An update can only be resumed if it is in the paused state.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt_ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.version = "9.5.0"
        resource.patch(hydrate=True, action="pause")

The call to update the software cluster version and/or firmware version returns the job UUID, including a HAL link to retrieve details about the job. The job object includes a `state` field and a message to indicate the progress of the job. When the job is complete and the application is fully created, the message indicates success and the `state` field of the job is set to `success`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Job

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Job(uuid="f587d316-5feb-11e8-b0e0-005056956dfc")
        resource.get()
        print(resource)

Try it out

    Job(
        {
            "message": "success",
            "state": "success",
            "code": 0,
            "uuid": "f587d316-5feb-11e8-b0e0-005056956dfc",
            "_links": {
                "self": {"href": "/api/cluster/jobs/f587d316-5feb-11e8-b0e0-005056956dfc"}
            },
            "description": "PATCH /api/cluster/software",
        }
    )

You can check the progress of the upgrade in the GET /cluster/software endpoint. The following example shows how to check the progress of the pause upgrade state after setting the `action` field to `pause`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Software()
        resource.get()
        print(resource)

Try it out

    Software(
        {
            "status_details": [
                {
                    "issue": {"code": 10551400, "message": "Installing software image."},
                    "node": {"name": "node1"},
                    "start_time": "2019-01-08T02:54:36+05:30",
                },
                {
                    "issue": {"code": 10551400, "message": "Installing software image."},
                    "node": {"name": "node2"},
                    "start_time": "2019-01-08T02:54:36+05:30",
                },
            ],
            "elapsed_duration": 103,
            "state": "pause_pending",
            "validation_results": [
                {
                    "action": {
                        "message": 'Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update.'
                    },
                    "issue": {
                        "message": 'Manual validation checks need to be performed. Refer to the Upgrade Advisor Plan or the "What should I verify before I upgrade with or without Upgrade Advisor" section in the "Upgrade ONTAP" documentation for the remaining validation checks that need to be performed before update. Failing to do so can result in an update failure or an I/O disruption.'
                    },
                    "status": "warning",
                    "update_check": "Manual checks",
                }
            ],
            "pending_version": "9.7.0",
            "estimated_duration": 5220,
            "_links": {"self": {"href": "/api/cluster/software"}},
            "version": "9.7.0",
            "nodes": [
                {
                    "firmware": {
                        "dqp": {
                            "revision": "20200117",
                            "version": "3.17",
                            "record_count": {
                                "device": 29,
                                "alias": 200,
                                "system": 3,
                                "drive": 680,
                            },
                            "file_name": "qual_devices_v2",
                        },
                        "shelf": {"update_status": "idle", "in_progress_count": 2},
                        "cluster_fw_progress": [
                            {
                                "update_type": "automated_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "abc.zip",
                            },
                            {
                                "update_type": "automated_update",
                                "job": {
                                    "_links": {
                                        "self": {
                                            "href": "/api/cluster/jobs/5a21663c-a9a0-11ea-af9a-005056bb44d7"
                                        }
                                    },
                                    "uuid": "5a21663c-a9a0-11ea-af9a-005056bb44d7",
                                },
                                "update_state": [
                                    {
                                        "message": "Cannot open the local staging zip file.",
                                        "worker_node": {
                                            "uuid": "fcd40f70-f531-11eb-b235-005056bb3497",
                                            "name": "Node 1",
                                        },
                                        "code": 2228325,
                                        "status": "failed",
                                        "attempts": 3,
                                    },
                                    {
                                        "message": "Success",
                                        "code": 0,
                                        "status": "complete",
                                        "attempts": 3,
                                    },
                                ],
                                "zip_file_name": "xyz.zip",
                            },
                        ],
                        "disk": {
                            "update_status": "idle",
                            "average_duration_per_disk": 120,
                            "total_completion_estimate": 0,
                            "num_waiting_download": 0,
                        },
                        "sp_bmc": {
                            "image": " primary",
                            "end_time": "2018-05-21T09:53:04+05:30",
                            "running_version": "1.2.3.4",
                            "is_current": True,
                            "in_progress": False,
                            "percent_done": 100,
                            "fw_type": "SP",
                            "start_time": "2018-05-21T09:53:04+05:30",
                        },
                    },
                    "version": "9.5.0",
                }
            ],
            "update_details": [
                {
                    "elapsed_duration": 54,
                    "phase": "Pre-update checks",
                    "estimated_duration": 600,
                    "node": {"name": "node1"},
                },
                {
                    "elapsed_duration": 49,
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                    "node": {"name": "node2"},
                },
                {
                    "elapsed_duration": 49,
                    "phase": "Data ONTAP updates",
                    "estimated_duration": 4620,
                },
            ],
        }
    )

### Downloading the software package

The following example shows how to download the software/firmware package from an HTTP or FTP server. Provide the `url`, `username`, and `password`, if required, to start the download of the package to the cluster.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import SoftwarePackageDownload

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = SoftwarePackageDownload()
        resource.url = "http://server/package"
        resource.username = "admin"
        resource.password = "*********"
        resource.post(hydrate=True, return_timeout=0)
        print(resource)

Try it out

    SoftwarePackageDownload(
        {"url": "http://server/package", "password": "*********", "username": "admin"}
    )

The call to download the software/firmware package returns the job UUID, including a HAL link to retrieve details about the job. The job object includes a `state` field and a message to indicate the progress of the job. When the job is complete and the application is fully created, the message indicates success and the job `state` field is set to `success`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Job

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Job(uuid="f587d316-5feb-11e8-b0e0-005056956dfc")
        resource.get()
        print(resource)

Try it out

    Job(
        {
            "message": "success",
            "state": "success",
            "code": 0,
            "uuid": "f587d316-5feb-11e8-b0e0-005056956dfc",
            "_links": {
                "self": {"href": "/api/cluster/jobs/f587d316-5feb-11e8-b0e0-005056956dfc"}
            },
            "description": "POST /api/cluster/software/download",
        }
    )

### Checking the progress of the software package being downloaded from an HTTP or FTP server

The following example shows how to retrieve the progress status of the software package being downloaded from a HTTP or FTP server.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import SoftwarePackageDownload

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = SoftwarePackageDownload()
        resource.get()
        print(resource)

Try it out

    SoftwarePackageDownload({})

#### HTTPS error codes

The following is a list of possible error codes that can be returned during a package download operation.
ONTAP Error Response Codes | Error Code | Description | | ---------- | ----------- | | 2228324 | Failed to access the remote zip file on node. | | 2228325 | Cannot open local staging ZIP file | | 2228326 | File copy to local staging failed. | | 2228327 | Firmware file already exists. | | 2228328 | Firmware update of node failed. | | 2228329 | Attempt to start worker on node failed | | 2228330 | Uploaded firmware file is not present. | | 2228331 | Copy of file from webserver failed. | | 2228428 | Firmware update completed with errors | | 2228429 | Firmware update completed. | | 10551327 | Package image with the same name already exists. | | 10551357 | Cannot perform an update when a previous update is still in progress. | | 10551381 | Package download failed. | | 10551382 | Package download is still running. | | 10551384 | Package download has not started. | | 10551496 | Failed to download package. | | 10551797 | Internal error. Failed to check if file upload is enabled. Contact technical support for assistance. | Also see the table of common errors in the Response body overview section of this documentation.

### Uploading a software/firmware package

The following example shows how to upload a software package.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Software

    with HostConnection(
        "<mgmt-ip>", username="username", password="password", verify=False
    ):
        resource = Software()
        resource.upload()

Try it out

    Software({})

#### HTTPS error codes

The following is a list of possible error codes that can be returned during a package upload operation.
ONTAP Error Response Codes | Error Code | Description | | ---------- | ----------- | | 2228324 | Failed to access the remote zip file on node. | | 2228325 | Cannot open local staging ZIP file | | 2228326 | File copy to local staging failed. | | 2228327 | Firmware file already exists. | | 2228328 | Firmware update of node failed. | | 2228329 | Attempt to start worker on node failed | | 2228330 | Uploaded firmware file is not present. | | 2228331 | Copy of file from webserver failed. | | 2228428 | Firmware update completed with errors | | 2228429 | Firmware update completed. | | 10551395 | Validation checks failed with warnings. | | 10551797 | Internal error. Failed to check if file upload is enabled. | | 10551798 | File upload is disabled. Enable file upload by setting "ApacheUploadEnabled 1" in the web services configuration file or contact technical support for assistance. | | 10551800 | Internal error. Access permissions restrict file upload. This is likely due to a bad web jail setup. Contact technical support for assistance. | | 10551801 | Internal error. A read/write error occurred when uploading this file. Contact technical support for assistance | | 10551802 | An invalid argument was supplied to create a file handle. Try uploading the file again or contact technical support for assistance. | | 10551803 | An unknown error occurred. Retry file upload operation again or contact technical support for assistance. | | 10551804 | Internal error. There is not sufficient space in the file upload directory to upload this file. Contact technical support for assistance. | | 10551805 | Internal error in JAIL setup. Contact technical support for assistance. | | 10551806 | Internal error. Failed to write to file in the webjail directory. Contact technical support for assistance. | | 10551807 | The request must only contain a single file. More than one file per request is not supported. | | 10551808 | The request must be of type multipart/form-data. | Also see the table of common errors in the Response body overview section of this documentation.

### Retrieving cluster software packages information

The following example shows how to retrieve the ONTAP software packages in a cluster.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import SoftwarePackage

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        print(list(SoftwarePackage.get_collection(return_timeout=15)))

Try it out

    [
        SoftwarePackage(
            {
                "_links": {"self": {"href": "/api/cluster/software/packages/9.7.0"}},
                "version": "9.7.0",
            }
        ),
        SoftwarePackage(
            {
                "_links": {"self": {"href": "/api/cluster/software/packages/9.5.0"}},
                "version": "9.5.0",
            }
        ),
    ]

The following example shows how to retrieve the details of a given cluster software package.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import SoftwarePackage

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = SoftwarePackage(version="9.7.0")
        resource.get()
        print(resource)

Try it out

    SoftwarePackage(
        {
            "_links": {"self": {"href": "/api/cluster/software/packages/9.7.0"}},
            "create_time": "2018-05-21T10:06:59+05:30",
            "version": "9.7.0",
        }
    )

### Deleting a cluster software package

The following example shows how to delete a package from the cluster. You need to provide the package version that you want to delete. The software package delete creates a job to perform the delete operation.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import SoftwarePackage

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = SoftwarePackage(version="9.6.0")
        resource.delete()

The call to delete the package returns the job UUID, including a HAL link to retrieve details about the job. The job object includes a `state` field and a message to indicate the progress of the job. When the job is complete and the application is fully created, the message indicates success and the job `state` field is set to `success`.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import Job

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        resource = Job(uuid="f587d316-5feb-11e8-b0e0-005056956dfc")
        resource.get()
        print(resource)

Try it out

    Job(
        {
            "message": "success",
            "state": "success",
            "code": 0,
            "uuid": "f587d316-5feb-11e8-b0e0-005056956dfc",
            "_links": {
                "self": {"href": "/api/cluster/jobs/f587d316-5feb-11e8-b0e0-005056956dfc"}
            },
            "description": "DELETE /api/cluster/software/packages/9.6.0",
        }
    )

#### HTTPS error codes

The following is a list of possible error codes that can be returned during a package delete operation.

    # ONTAP Error Response codes
    | ----------- | -------------------------------------------------------- |
    | Error codes |                     Description                          |
    | ----------- | -------------------------------------------------------- |
    | 10551315    | Package store is empty                                   |
    | 10551322    | Error in retrieving package cleanup status               |
    | 10551323    | Error in cleaning up package information on a node       |
    | 10551324    | Error in cleaning up package information on both nodes   |
    | 10551325    | Package does not exist on the system                     |
    | 10551326    | Error in deleting older package cleanup tasks            |
    | 10551346    | Package delete failed since a validation is in progress  |
    | 10551347    | Package delete failed since an update is in progress     |
    | 10551367    | A package synchronization is in progress                 |
    | 10551388    | Package delete operation timed out                       |
    | 10551566    | Validation is not completed on the MetroCluster partner  |
    |             | cluster                                                  |
    | 10551567    | Package version is not available in the package          |
    |             | repository on the MetroCluster partner cluster           |
    | ----------- | -------------------------------------------------------- |

### Retrieving software installation history information

The following example shows how to: - retrieve the software package installation history information. - display specific node level software installation history information. - provide all the attributes by default in response when the self referential link is not present.

    from netapp_ontap import HostConnection
    from netapp_ontap.resources import SoftwareHistory

    with HostConnection("<mgmt-ip>", username="admin", password="password", verify=False):
        print(list(SoftwareHistory.get_collection()))

Try it out

    SoftwareHistory(
        {
            "to_version": "9.5.0",
            "state": "successful",
            "from_version": "9.4.0",
            "end_time": "2018-05-21T10:14:51+05:30",
            "node": {
                "_links": {
                    "self": {
                        "href": "/api/cluster/nodes/58cd3a2b-af63-11e8-8b0d-0050568e7279"
                    }
                },
                "uuid": "58cd3a2b-af63-11e8-8b0d-0050568e7279",
                "name": "sti70-vsim-ucs165n",
            },
            "start_time": "2018-09-03T16:18:46+05:30",
        }
    )

## Classes

`class Software (*args, **kwargs)`

  Allows interaction with Software objects on the host

  Initialize the instance of the resource.

  Any keyword arguments are set on the instance as properties. For example, if the class was named 'MyResource', then this statement would be true:

      MyResource(name='foo').name == 'foo'

  ## Args

  `*args`
    Each positional argument represents a parent key as used in the URL of the object. That is, each value will be used to fill in a segment of the URL which refers to some parent object. The order of these arguments must match the order they are specified in the URL, from left to right.
  `**kwargs`
    each entry will have its key set as an attribute name on the instance and its value will be the value of that attribute.

  ### Ancestors

  - Resource

  ### Methods

  `def get (self, **kwargs) -> NetAppResponse`

    Retrieves the software profile of a cluster.

    ### Related ONTAP commands

    - `cluster image show`
    - `cluster image show-update-progress`
    - `system node image package show`

    ### Learn more

    - `DOC /cluster/software`

    Fetch the details of the object from the host.

    Requires the keys to be set (if any). After returning, new or changed properties from the host will be set on the instance.

    ## Returns

    A `NetAppResponse` object containing the details of the HTTP response.

    ## Raises

    `NetAppRestError`: If the API call returned a status code >= 400

  `def patch (self, hydrate: bool = False, poll: bool = True, poll_interval: Optional[int] = None, poll_timeout: Optional[int] = None, **kwargs) -> NetAppResponse`

    Updates the cluster software version. Important note: * Setting 'version' triggers the package installation. * To validate the package for installation but not perform the installation, use the `validate_only` field on the request.

    ### Required properties

    - `version` - Software version to be installed on the cluster.

    ### Recommended optional parameters

    - `validate_only` - Required to validate a software package before an upgrade.
    - `skip_warnings` - Used to skip validation warnings when starting a software upgrade.
    - `action` - Used to pause, resume, or cancel an ongoing software upgrade.
    - `stabilize_minutes` - Specifies a custom value between 1 to 60 minutes that allows each node a specified amount of time to stabilize after a reboot; the default is 8 minutes.
    - `estimate_only` - Estimates the time duration; does not perform any update.
    - `nodes_to_update` - Specifies a subset of the cluster's nodes for update.
    - `show_validation_details` - If the value is set to true, then all validation details will be shown in the output.

    ### Related ONTAP commands

    - `cluster image validate`
    - `cluster image update`
    - `cluster image pause-update`
    - `cluster image resume-update`
    - `cluster image cancel-update`

    ### Learn more

    - `DOC /cluster/software`

    Send the difference in the object's state to the host as a modification request.

    Calculates the difference in the object's state since the last time we interacted with the host and sends this in the request body.

    ## Args

    `hydrate`
      If set to True, after the response is received from the call, a a GET call will be made to refresh all fields of the object.
    `poll`
      If set to True, the call will not return until the asynchronous job on the host has completed. Has no effect if the host did not return a job response.
    `poll_interval`
      If the operation returns a job, this specifies how often to query the job for updates.
    `poll_timeout`
      If the operation returns a job, this specifies how long to continue monitoring the job's status for completion.
    `connection`
      The `HostConnection` object to use for this API call. If unset, tries to use the connection which is set globally for the library or from the current context.
    `**kwargs`
      Any key/value pairs passed will normally be sent as query parameters to the host. If any of these pairs are parameters that are sent as formdata then only parameters of that type will be accepted and all others will be discarded.

    ## Returns

    A `NetAppResponse` object containing the details of the HTTP response.

    ## Raises

    `NetAppRestError`: If the API call returned a status code >= 400

  `def upload (self, body: Union[Resource, dict] = None, poll: bool = True, poll_interval: Optional[int] = None, poll_timeout: Optional[int] = None, **kwargs) -> NetAppResponse`

    Uploads a software or firmware package located on the local filesystem.

    ### Related ONTAP commands

    - `cluster image package get`

    ### Learn more

    - `DOC /cluster/software`

    Perform a custom action on this resource which is not a simple CRUD action

    ## Args

    `path`
      The action verb for this request. This will be added as a postfix to the instance location of the resource.
    `body`
      The body of the action request. This should be a Resource instance. The connection and URL will be determined based on the values from this object.
    `poll`
      If set to True, the call will not return until the asynchronous job on the host has completed. Has no effect if the host did not return a job response.
    `poll_interval`
      If the operation returns a job, this specifies how often to query the job for updates.
    `poll_timeout`
      If the operation returns a job, this specifies how long to continue monitoring the job's status for completion.
    `**kwargs`
      Any key/value pairs passed will be sent as query parameters to the host.

    ## Returns

    A `NetAppResponse` object containing the details of the HTTP response.

    ## Raises

    `NetAppRestError`: If the API call returned a status code >= 400

  ### Inherited members

  - `Resource`:
    - `from_dict`
    - `get_collection_url`
    - `get_connection`
    - `instance_location`
    - `path_keys`
    - `poll`
    - `set_connection`
    - `to_dict`
`class SoftwareSchema (*, only: Union[Sequence[str], Set[str]] = None, exclude: Union[Sequence[str], Set[str]] = (), many: bool = False, context: Dict = None, load_only: Union[Sequence[str], Set[str]] = (), dump_only: Union[Sequence[str], Set[str]] = (), partial: Union[bool, Sequence[str], Set[str]] = False, unknown: str = None)`

  The fields of the Software object

  ### Ancestors

  - netapp_ontap.resource.ResourceSchema
  - marshmallow.schema.Schema
  - marshmallow.base.SchemaABC

  ### Class variables

  `action: str GET POST PATCH`

    User triggered action to apply to the install operation

    Valid choices:

    - pause
    - cancel
    - resume
  `elapsed_duration: Size GET`

    Elapsed time during the upgrade or validation operation

    Example: 2140

  `estimated_duration: Size GET`

    Overall estimated time for completion of the upgrade or validation operation.

    Example: 5220

  `links: SelfLink GET`

    The links field of the software.

  `metrocluster: SoftwareReferenceMetrocluster GET POST PATCH`

    The metrocluster field of the software.

  `nodes: List[SoftwareNode] GET`

    List of nodes, active versions, and firmware update progressions.

  `pending_version: str GET`

    Version being installed on the system.

    Example: ONTAP_X_1

  `post_update_checks: List[SoftwareValidation] GET`

    List of failed post-update checks' warnings, errors, and advice.

  `state: str GET`

    Operational state of the upgrade

    Valid choices:

    - in_progress
    - waiting
    - paused_by_user
    - paused_on_error
    - completed
    - canceled
    - failed
    - pause_pending
    - cancel_pending
  `status_details: List[SoftwareStatusDetails] GET`

    Display status details.

  `update_details: List[SoftwareUpdateDetails] GET`

    Display update progress details.

  `validation_results: List[SoftwareValidation] GET`

    List of validation warnings, errors, and advice.

  `version: str GET POST PATCH`

    Version of ONTAP installed and currently active on the system. During PATCH, using the 'validate_only' parameter on the request executes pre-checks, but does not perform the full installation.

    Example: ONTAP_X