github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/baremetal/v1/nodes/testing/fixtures_test.go (about)

     1  package testing
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"testing"
     7  	"time"
     8  
     9  	inventorytest "github.com/vnpaycloud-console/gophercloud/v2/openstack/baremetal/inventory/testing"
    10  	"github.com/vnpaycloud-console/gophercloud/v2/openstack/baremetal/v1/nodes"
    11  	th "github.com/vnpaycloud-console/gophercloud/v2/testhelper"
    12  	"github.com/vnpaycloud-console/gophercloud/v2/testhelper/client"
    13  )
    14  
    15  // NodeListBody contains the canned body of a nodes.List response, without detail.
    16  const NodeListBody = `
    17   {
    18    "nodes": [
    19      {
    20        "instance_uuid": null,
    21        "links": [
    22          {
    23            "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
    24            "rel": "self"
    25          },
    26          {
    27            "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
    28            "rel": "bookmark"
    29          }
    30        ],
    31        "maintenance": false,
    32        "name": "foo",
    33        "power_state": null,
    34        "provision_state": "enroll"
    35      },
    36      {
    37        "instance_uuid": null,
    38        "links": [
    39          {
    40            "href": "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662",
    41            "rel": "self"
    42          },
    43          {
    44            "href": "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662",
    45            "rel": "bookmark"
    46          }
    47        ],
    48        "maintenance": false,
    49        "name": "bar",
    50        "power_state": null,
    51        "provision_state": "enroll"
    52      },
    53      {
    54        "instance_uuid": null,
    55        "links": [
    56          {
    57            "href": "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474",
    58            "rel": "self"
    59          },
    60          {
    61            "href": "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474",
    62            "rel": "bookmark"
    63          }
    64        ],
    65        "maintenance": false,
    66        "name": "baz",
    67        "power_state": null,
    68        "provision_state": "enroll"
    69      }
    70    ]
    71  }
    72  `
    73  
    74  // NodeListDetailBody contains the canned body of a nodes.ListDetail response.
    75  const NodeListDetailBody = `
    76   {
    77    "nodes": [
    78      {
    79        "automated_clean": null,
    80        "bios_interface": "no-bios",
    81        "boot_interface": "pxe",
    82        "chassis_uuid": null,
    83        "clean_step": {},
    84        "conductor_group": "",
    85        "console_enabled": false,
    86        "console_interface": "no-console",
    87        "created_at": "2019-01-31T19:59:28+00:00",
    88        "deploy_interface": "iscsi",
    89        "deploy_step": {},
    90        "disable_power_off": false,
    91        "driver": "ipmi",
    92        "driver_info": {
    93          "ipmi_port": "6230",
    94          "ipmi_username": "admin",
    95          "deploy_kernel": "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz",
    96          "ipmi_address": "192.168.122.1",
    97          "deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz",
    98          "ipmi_password": "admin"
    99  
   100        },
   101        "driver_internal_info": {},
   102        "extra": {},
   103        "fault": null,
   104        "firmware_interface": "no-firmware",
   105        "inspect_interface": "no-inspect",
   106        "inspection_finished_at": null,
   107        "inspection_started_at": null,
   108        "instance_info": {},
   109        "instance_uuid": null,
   110        "last_error": null,
   111        "links": [
   112          {
   113            "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
   114            "rel": "self"
   115          },
   116          {
   117            "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
   118            "rel": "bookmark"
   119          }
   120        ],
   121        "maintenance": false,
   122        "maintenance_reason": null,
   123        "management_interface": "ipmitool",
   124        "name": "foo",
   125        "network_interface": "flat",
   126        "portgroups": [
   127          {
   128            "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/portgroups",
   129            "rel": "self"
   130          },
   131          {
   132            "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/portgroups",
   133            "rel": "bookmark"
   134          }
   135        ],
   136        "ports": [
   137          {
   138            "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/ports",
   139            "rel": "self"
   140          },
   141          {
   142            "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/ports",
   143            "rel": "bookmark"
   144          }
   145        ],
   146        "power_interface": "ipmitool",
   147        "power_state": null,
   148        "properties": {},
   149        "provision_state": "enroll",
   150        "provision_updated_at": "2019-02-15T17:21:29+00:00",
   151        "raid_config": {},
   152        "raid_interface": "no-raid",
   153        "retired": false,
   154        "retired_reason": "No longer needed",
   155        "rescue_interface": "no-rescue",
   156        "reservation": null,
   157        "resource_class": null,
   158        "states": [
   159          {
   160            "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/states",
   161            "rel": "self"
   162          },
   163          {
   164            "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/states",
   165            "rel": "bookmark"
   166          }
   167        ],
   168        "storage_interface": "noop",
   169        "target_power_state": null,
   170        "target_provision_state": null,
   171        "target_raid_config": {},
   172        "traits": [],
   173        "updated_at": "2019-02-15T19:59:29+00:00",
   174        "uuid": "d2630783-6ec8-4836-b556-ab427c4b581e",
   175        "vendor_interface": "ipmitool",
   176        "volume": [
   177          {
   178            "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/volume",
   179            "rel": "self"
   180          },
   181          {
   182            "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/volume",
   183            "rel": "bookmark"
   184          }
   185        ]
   186      },
   187      {
   188        "automated_clean": null,
   189        "bios_interface": "no-bios",
   190        "boot_interface": "pxe",
   191        "chassis_uuid": null,
   192        "clean_step": {},
   193        "conductor_group": "",
   194        "console_enabled": false,
   195        "console_interface": "no-console",
   196        "created_at": "2019-01-31T19:59:29+00:00",
   197        "deploy_interface": "iscsi",
   198        "deploy_step": {},
   199        "disable_power_off": false,
   200        "driver": "ipmi",
   201        "driver_info": {},
   202        "driver_internal_info": {},
   203        "extra": {},
   204        "fault": null,
   205        "firmware_interface": "no-firmware",
   206        "inspect_interface": "no-inspect",
   207        "inspection_finished_at": "2023-02-02T14:45:59.705249Z",
   208        "inspection_started_at": "2023-02-02T14:35:59.682403Z",
   209        "instance_info": {},
   210        "instance_uuid": null,
   211        "last_error": null,
   212        "links": [
   213          {
   214            "href": "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662",
   215            "rel": "self"
   216          },
   217          {
   218            "href": "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662",
   219            "rel": "bookmark"
   220          }
   221        ],
   222        "maintenance": false,
   223        "maintenance_reason": null,
   224        "management_interface": "ipmitool",
   225        "name": "bar",
   226        "network_interface": "flat",
   227        "portgroups": [
   228          {
   229            "href": "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/portgroups",
   230            "rel": "self"
   231          },
   232          {
   233            "href": "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/portgroups",
   234            "rel": "bookmark"
   235          }
   236        ],
   237        "ports": [
   238          {
   239            "href": "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/ports",
   240            "rel": "self"
   241          },
   242          {
   243            "href": "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/ports",
   244            "rel": "bookmark"
   245          }
   246        ],
   247        "power_interface": "ipmitool",
   248        "power_state": null,
   249        "properties": {},
   250        "provision_state": "available",
   251        "provision_updated_at": null,
   252        "raid_config": {},
   253        "raid_interface": "no-raid",
   254        "retired": false,
   255        "retired_reason": "No longer needed",
   256        "rescue_interface": "no-rescue",
   257        "reservation": null,
   258        "resource_class": null,
   259        "states": [
   260          {
   261            "href": "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/states",
   262            "rel": "self"
   263          },
   264          {
   265            "href": "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/states",
   266            "rel": "bookmark"
   267          }
   268        ],
   269        "storage_interface": "noop",
   270        "target_power_state": null,
   271        "target_provision_state": null,
   272        "target_raid_config": {},
   273        "traits": [],
   274        "updated_at": "2019-02-15T19:59:29+00:00",
   275        "uuid": "08c84581-58f5-4ea2-a0c6-dd2e5d2b3662",
   276        "vendor_interface": "ipmitool",
   277        "volume": [
   278          {
   279            "href": "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/volume",
   280            "rel": "self"
   281          },
   282          {
   283            "href": "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/volume",
   284            "rel": "bookmark"
   285          }
   286        ]
   287      },
   288      {
   289        "automated_clean": null,
   290        "bios_interface": "no-bios",
   291        "boot_interface": "pxe",
   292        "chassis_uuid": null,
   293        "clean_step": {},
   294        "conductor_group": "",
   295        "console_enabled": false,
   296        "console_interface": "no-console",
   297        "created_at": "2019-01-31T19:59:30+00:00",
   298        "deploy_interface": "iscsi",
   299        "deploy_step": {},
   300        "disable_power_off": true,
   301        "driver": "ipmi",
   302        "driver_info": {},
   303        "driver_internal_info": {},
   304        "extra": {},
   305        "fault": null,
   306        "firmware_interface": "no-firmware",
   307        "inspect_interface": "no-inspect",
   308        "inspection_finished_at": null,
   309        "inspection_started_at": null,
   310        "instance_info": {},
   311        "instance_uuid": null,
   312        "last_error": null,
   313        "links": [
   314          {
   315            "href": "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474",
   316            "rel": "self"
   317          },
   318          {
   319            "href": "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474",
   320            "rel": "bookmark"
   321          }
   322        ],
   323        "maintenance": false,
   324        "maintenance_reason": null,
   325        "management_interface": "ipmitool",
   326        "name": "baz",
   327        "network_interface": "flat",
   328        "portgroups": [
   329          {
   330            "href": "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/portgroups",
   331            "rel": "self"
   332          },
   333          {
   334            "href": "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/portgroups",
   335            "rel": "bookmark"
   336          }
   337        ],
   338        "ports": [
   339          {
   340            "href": "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/ports",
   341            "rel": "self"
   342          },
   343          {
   344            "href": "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/ports",
   345            "rel": "bookmark"
   346          }
   347        ],
   348        "power_interface": "ipmitool",
   349        "power_state": null,
   350        "properties": {},
   351        "provision_state": "enroll",
   352        "provision_updated_at": null,
   353        "raid_config": {},
   354        "raid_interface": "no-raid",
   355        "retired": false,
   356        "retired_reason": "No longer needed",
   357        "rescue_interface": "no-rescue",
   358        "reservation": null,
   359        "resource_class": null,
   360        "states": [
   361          {
   362            "href": "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/states",
   363            "rel": "self"
   364          },
   365          {
   366            "href": "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/states",
   367            "rel": "bookmark"
   368          }
   369        ],
   370        "storage_interface": "noop",
   371        "target_power_state": null,
   372        "target_provision_state": null,
   373        "target_raid_config": {},
   374        "traits": [],
   375        "updated_at": "2019-02-15T19:59:29+00:00",
   376        "uuid": "c9afd385-5d89-4ecb-9e1c-68194da6b474",
   377        "vendor_interface": "ipmitool",
   378        "volume": [
   379          {
   380            "href": "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/volume",
   381            "rel": "self"
   382          },
   383          {
   384            "href": "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/volume",
   385            "rel": "bookmark"
   386          }
   387        ]
   388      }
   389    ]
   390  }
   391  `
   392  
   393  // SingleNodeBody is the canned body of a Get request on an existing node.
   394  const SingleNodeBody = `
   395  {
   396    "automated_clean": null,
   397    "bios_interface": "no-bios",
   398    "boot_interface": "pxe",
   399    "chassis_uuid": null,
   400    "clean_step": {},
   401    "conductor_group": "",
   402    "console_enabled": false,
   403    "console_interface": "no-console",
   404    "created_at": "2019-01-31T19:59:28+00:00",
   405    "deploy_interface": "iscsi",
   406    "deploy_step": {},
   407    "driver": "ipmi",
   408    "driver_info": {
   409      "ipmi_port": "6230",
   410      "ipmi_username": "admin",
   411      "deploy_kernel": "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz",
   412      "ipmi_address": "192.168.122.1",
   413      "deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz",
   414      "ipmi_password": "admin"
   415    },
   416    "driver_internal_info": {},
   417    "extra": {},
   418    "fault": null,
   419    "firmware_interface": "no-firmware",
   420    "inspect_interface": "no-inspect",
   421    "inspection_finished_at": null,
   422    "inspection_started_at": null,
   423    "instance_info": {},
   424    "instance_uuid": null,
   425    "last_error": null,
   426    "links": [
   427      {
   428        "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
   429        "rel": "self"
   430      },
   431      {
   432        "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
   433        "rel": "bookmark"
   434      }
   435    ],
   436    "maintenance": false,
   437    "maintenance_reason": null,
   438    "management_interface": "ipmitool",
   439    "name": "foo",
   440    "network_interface": "flat",
   441    "portgroups": [
   442      {
   443        "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/portgroups",
   444        "rel": "self"
   445      },
   446      {
   447        "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/portgroups",
   448        "rel": "bookmark"
   449      }
   450    ],
   451    "ports": [
   452      {
   453        "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/ports",
   454        "rel": "self"
   455      },
   456      {
   457        "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/ports",
   458        "rel": "bookmark"
   459      }
   460    ],
   461    "power_interface": "ipmitool",
   462    "power_state": null,
   463    "properties": {},
   464    "provision_state": "enroll",
   465    "provision_updated_at": "2019-02-15T17:21:29+00:00",
   466    "raid_config": {},
   467    "raid_interface": "no-raid",
   468    "retired": false,
   469    "retired_reason": "No longer needed",
   470    "rescue_interface": "no-rescue",
   471    "reservation": null,
   472    "resource_class": null,
   473    "states": [
   474      {
   475        "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/states",
   476        "rel": "self"
   477      },
   478      {
   479        "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/states",
   480        "rel": "bookmark"
   481      }
   482    ],
   483    "storage_interface": "noop",
   484    "target_power_state": null,
   485    "target_provision_state": null,
   486    "target_raid_config": {},
   487    "traits": [],
   488    "updated_at": "2019-02-15T19:59:29+00:00",
   489    "uuid": "d2630783-6ec8-4836-b556-ab427c4b581e",
   490    "vendor_interface": "ipmitool",
   491    "volume": [
   492      {
   493        "href": "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/volume",
   494        "rel": "self"
   495      },
   496      {
   497        "href": "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/volume",
   498        "rel": "bookmark"
   499      }
   500    ]
   501  }
   502  `
   503  
   504  const NodeValidationBody = `
   505  {
   506    "bios": {
   507      "reason": "Driver ipmi does not support bios (disabled or not implemented).",
   508      "result": false
   509    },
   510    "boot": {
   511      "reason": "Cannot validate image information for node a62b8495-52e2-407b-b3cb-62775d04c2b8 because one or more parameters are missing from its instance_info and insufficent information is present to boot from a remote volume. Missing are: ['ramdisk', 'kernel', 'image_source']",
   512      "result": false
   513    },
   514    "console": {
   515      "reason": "Driver ipmi does not support console (disabled or not implemented).",
   516      "result": false
   517    },
   518    "deploy": {
   519      "reason": "Cannot validate image information for node a62b8495-52e2-407b-b3cb-62775d04c2b8 because one or more parameters are missing from its instance_info and insufficent information is present to boot from a remote volume. Missing are: ['ramdisk', 'kernel', 'image_source']",
   520      "result": false
   521    },
   522    "firmware": {
   523      "reason": "Driver ipmi does not support firmware (disabled or not implemented).",
   524      "result": false
   525    },
   526    "inspect": {
   527      "reason": "Driver ipmi does not support inspect (disabled or not implemented).",
   528      "result": false
   529    },
   530    "management": {
   531      "result": true
   532    },
   533    "network": {
   534      "result": true
   535    },
   536    "power": {
   537      "result": true
   538    },
   539    "raid": {
   540      "reason": "Driver ipmi does not support raid (disabled or not implemented).",
   541      "result": false
   542    },
   543    "rescue": {
   544      "reason": "Driver ipmi does not support rescue (disabled or not implemented).",
   545      "result": false
   546    },
   547    "storage": {
   548      "result": true
   549    }
   550  }
   551  `
   552  
   553  const NodeBootDeviceBody = `
   554  {
   555    "boot_device":"pxe",
   556    "persistent":false
   557  }
   558  `
   559  
   560  const NodeSupportedBootDeviceBody = `
   561  {
   562    "supported_boot_devices": [
   563      "pxe",
   564      "disk"
   565    ]
   566  }
   567  `
   568  
   569  const NodeProvisionStateActiveBody = `
   570  {
   571      "target": "active",
   572      "configdrive": "http://127.0.0.1/images/test-node-config-drive.iso.gz"
   573  }
   574  `
   575  
   576  const NodeProvisionStateActiveBodyWithSteps = `
   577  {
   578      "target": "active",
   579      "deploy_steps": [
   580  	{
   581  	    "interface": "deploy",
   582  	    "step": "inject_files",
   583  	    "priority": 50,
   584  	    "args": {
   585  		"files": []
   586  	    }
   587  	}
   588      ]
   589  }
   590  `
   591  
   592  const NodeProvisionStateCleanBody = `
   593  {
   594      "target": "clean",
   595      "clean_steps": [
   596          {
   597              "interface": "deploy",
   598              "step": "upgrade_firmware",
   599              "args": {
   600                  "force": "True"
   601              }
   602          }
   603      ]
   604  }
   605  `
   606  
   607  const NodeProvisionStateConfigDriveBody = `
   608  {
   609  	"target": "active",
   610  	"configdrive": {
   611  		"user_data": {
   612  			"ignition": {
   613  			"version": "2.2.0"
   614  			},
   615  			"systemd": {
   616  				"units": [
   617  					{
   618  						"enabled": true,
   619  						"name": "example.service"
   620  					}
   621  				]
   622  			}
   623  		}
   624  	}
   625  }
   626  `
   627  
   628  const NodeProvisionStateServiceBody = `
   629  {
   630      "target": "service",
   631      "service_steps": [
   632          {
   633              "interface": "bios",
   634              "step": "apply_configuration",
   635              "args": {
   636  		"settings": []
   637              }
   638          }
   639      ]
   640  }
   641  `
   642  
   643  const NodeBIOSSettingsBody = `
   644  {
   645    "bios": [
   646     {
   647        "name": "Proc1L2Cache",
   648        "value": "10x256 KB"
   649     },
   650     {
   651        "name": "Proc1NumCores",
   652        "value": "10"
   653     },
   654     {
   655        "name": "ProcVirtualization",
   656        "value": "Enabled"
   657     }
   658     ]
   659  }
   660  `
   661  
   662  const NodeDetailBIOSSettingsBody = `
   663  {
   664    "bios": [
   665     {
   666        "created_at": "2021-05-11T21:33:44+00:00",
   667        "updated_at": null,
   668        "name": "Proc1L2Cache",
   669        "value": "10x256 KB",
   670        "attribute_type": "String",
   671        "allowable_values": [],
   672        "lower_bound": null,
   673        "max_length": 16,
   674        "min_length": 0,
   675        "read_only": true,
   676        "reset_required": null,
   677        "unique": null,
   678        "upper_bound": null,
   679        "links": [
   680          {
   681            "href": "http://ironic.example.com:6385/v1/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1L2Cache",
   682            "rel": "self"
   683          },
   684          {
   685            "href": "http://ironic.example.com:6385/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1L2Cache",
   686            "rel": "bookmark"
   687          }
   688        ]
   689     },
   690     {
   691        "created_at": "2021-05-11T21:33:44+00:00",
   692        "updated_at": null,
   693        "name": "Proc1NumCores",
   694        "value": "10",
   695        "attribute_type": "Integer",
   696        "allowable_values": [],
   697        "lower_bound": 0,
   698        "max_length": null,
   699        "min_length": null,
   700        "read_only": true,
   701        "reset_required": null,
   702        "unique": null,
   703        "upper_bound": 20,
   704        "links": [
   705          {
   706            "href": "http://ironic.example.com:6385/v1/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1NumCores",
   707            "rel": "self"
   708          },
   709          {
   710            "href": "http://ironic.example.com:6385/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/Proc1NumCores",
   711            "rel": "bookmark"
   712          }
   713        ]
   714     },
   715     {
   716        "created_at": "2021-05-11T21:33:44+00:00",
   717        "updated_at": null,
   718        "name": "ProcVirtualization",
   719        "value": "Enabled",
   720        "attribute_type": "Enumeration",
   721        "allowable_values": [
   722          "Enabled",
   723          "Disabled"
   724        ],
   725        "lower_bound": null,
   726        "max_length": null,
   727        "min_length": null,
   728        "read_only": false,
   729        "reset_required": null,
   730        "unique": null,
   731        "upper_bound": null,
   732        "links": [
   733          {
   734            "href": "http://ironic.example.com:6385/v1/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/ProcVirtualization",
   735            "rel": "self"
   736          },
   737          {
   738            "href": "http://ironic.example.com:6385/nodes/d26115bf-1296-4ca8-8c86-6f310d8ec375/bios/ProcVirtualization",
   739            "rel": "bookmark"
   740          }
   741        ]
   742     }
   743     ]
   744  }
   745  `
   746  
   747  const NodeSingleBIOSSettingBody = `
   748  {
   749    "Setting": {
   750        "name": "ProcVirtualization",
   751        "value": "Enabled"
   752     }
   753  }
   754  `
   755  
   756  const NodeVendorPassthruMethodsBody = `
   757  {
   758    "create_subscription": {
   759      "http_methods": [
   760        "POST"
   761      ],
   762      "async": false,
   763      "description": "",
   764      "attach": false,
   765      "require_exclusive_lock": true
   766    },
   767    "delete_subscription": {
   768      "http_methods": [
   769        "DELETE"
   770      ],
   771      "async": false,
   772      "description": "",
   773      "attach": false,
   774      "require_exclusive_lock": true
   775    },
   776    "get_subscription": {
   777      "http_methods": [
   778        "GET"
   779      ],
   780      "async": false,
   781      "description": "",
   782      "attach": false,
   783      "require_exclusive_lock": true
   784    },
   785    "get_all_subscriptions": {
   786      "http_methods": [
   787        "GET"
   788      ],
   789      "async": false,
   790      "description": "",
   791      "attach": false,
   792      "require_exclusive_lock": true
   793    }
   794  }
   795  `
   796  
   797  const NodeGetAllSubscriptionsVnedorPassthruBody = `
   798  {
   799    "@odata.context": "/redfish/v1/$metadata#EventDestinationCollection.EventDestinationCollection",
   800    "@odata.id": "/redfish/v1/EventService/Subscriptions",
   801    "@odata.type": "#EventDestinationCollection.EventDestinationCollection",
   802    "Description": "List of Event subscriptions",
   803    "Members": [
   804      {
   805        "@odata.id": "/redfish/v1/EventService/Subscriptions/62dbd1b6-f637-11eb-b551-4cd98f20754c"
   806      }
   807    ],
   808    "Members@odata.count": 1,
   809    "Name": "Event Subscriptions Collection"
   810  }
   811  
   812  `
   813  
   814  const NodeGetSubscriptionVendorPassthruBody = `
   815  {
   816    "Context": "Ironic",
   817    "Destination": "https://192.168.0.1/EventReceiver.php",
   818    "EventTypes": ["Alert"],
   819    "Id": "62dbd1b6-f637-11eb-b551-4cd98f20754c",
   820    "Protocol": "Redfish"
   821  }
   822  `
   823  
   824  const NodeCreateSubscriptionVendorPassthruAllParametersBody = `
   825  {
   826    "Context": "gophercloud",
   827    "Destination": "https://someurl",
   828    "EventTypes": ["Alert"],
   829    "HttpHeaders": [{"Context-Type":"application/json"}],
   830    "Id": "eaa43e2-018a-424e-990a-cbf47c62ef80",
   831    "Protocol": "Redfish"
   832  }
   833  `
   834  
   835  const NodeCreateSubscriptionVendorPassthruRequiredParametersBody = `
   836  {
   837    "Context": "",
   838    "Destination": "https://somedestinationurl",
   839    "EventTypes": ["Alert"],
   840    "Id": "344a3e2-978a-444e-990a-cbf47c62ef88",
   841    "Protocol": "Redfish"
   842  }
   843  `
   844  
   845  const NodeSetMaintenanceBody = `
   846  {
   847    "reason": "I'm tired"
   848  }
   849  `
   850  
   851  var NodeInventoryBody = fmt.Sprintf(`
   852  {
   853    "inventory": %s,
   854    "plugin_data":{
   855      "macs":[
   856        "52:54:00:90:35:d6"
   857      ],
   858      "local_gb":10,
   859      "cpu_arch":"x86_64",
   860      "memory_mb":2048
   861    }
   862  }
   863  `, inventorytest.InventorySample)
   864  
   865  const NodeFirmwareListBody = `
   866  {
   867    "firmware": [
   868     {
   869        "created_at": "2023-10-03T18:30:00+00:00",
   870        "updated_at": null,
   871        "component": "bios",
   872        "initial_version": "U30 v2.36 (07/16/2020)",
   873        "current_version": "U30 v2.36 (07/16/2020)",
   874        "last_version_flashed": null
   875     },
   876     {
   877        "created_at": "2023-10-03T18:30:00+00:00",
   878        "updated_at": "2023-10-03T18:45:54+00:00",
   879        "component": "bmc",
   880        "initial_version": "iLO 5 v2.78",
   881        "current_version": "iLO 5 v2.81",
   882        "last_version_flashed": "iLO 5 v2.81"
   883     }
   884     ]
   885  }
   886  `
   887  
   888  const NodeVirtualMediaAttachBody = `
   889  {
   890      "image_url": "https://example.com/image",
   891      "device_type": "cdrom"
   892  }
   893  `
   894  
   895  const NodeVirtualMediaAttachBodyWithSource = `
   896  {
   897      "image_url": "https://example.com/image",
   898      "device_type": "cdrom",
   899      "image_download_source": "http"
   900  }
   901  `
   902  
   903  var (
   904  	createdAtFoo, _      = time.Parse(time.RFC3339, "2019-01-31T19:59:28+00:00")
   905  	createdAtBar, _      = time.Parse(time.RFC3339, "2019-01-31T19:59:29+00:00")
   906  	createdAtBaz, _      = time.Parse(time.RFC3339, "2019-01-31T19:59:30+00:00")
   907  	updatedAt, _         = time.Parse(time.RFC3339, "2019-02-15T19:59:29+00:00")
   908  	provisonUpdatedAt, _ = time.Parse(time.RFC3339, "2019-02-15T17:21:29+00:00")
   909  
   910  	NodeFoo = nodes.Node{
   911  		UUID:                 "d2630783-6ec8-4836-b556-ab427c4b581e",
   912  		Name:                 "foo",
   913  		PowerState:           "",
   914  		TargetPowerState:     "",
   915  		ProvisionState:       "enroll",
   916  		TargetProvisionState: "",
   917  		Maintenance:          false,
   918  		MaintenanceReason:    "",
   919  		Fault:                "",
   920  		LastError:            "",
   921  		Reservation:          "",
   922  		Driver:               "ipmi",
   923  		DriverInfo: map[string]any{
   924  			"ipmi_port":      "6230",
   925  			"ipmi_username":  "admin",
   926  			"deploy_kernel":  "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz",
   927  			"ipmi_address":   "192.168.122.1",
   928  			"deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz",
   929  			"ipmi_password":  "admin",
   930  		},
   931  		DriverInternalInfo: map[string]any{},
   932  		Properties:         map[string]any{},
   933  		InstanceInfo:       map[string]any{},
   934  		InstanceUUID:       "",
   935  		ChassisUUID:        "",
   936  		Extra:              map[string]any{},
   937  		ConsoleEnabled:     false,
   938  		RAIDConfig:         map[string]any{},
   939  		TargetRAIDConfig:   map[string]any{},
   940  		CleanStep:          map[string]any{},
   941  		DeployStep:         map[string]any{},
   942  		Links: []nodes.Link{
   943  			{
   944  				Href: "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
   945  				Rel:  "self",
   946  			},
   947  			{
   948  				Href: "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e",
   949  				Rel:  "bookmark",
   950  			},
   951  		},
   952  		Ports: []nodes.Link{
   953  			{
   954  				Href: "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/ports",
   955  				Rel:  "self",
   956  			},
   957  			{
   958  				Href: "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/ports",
   959  				Rel:  "bookmark",
   960  			},
   961  		},
   962  		PortGroups: []nodes.Link{
   963  			{
   964  				Href: "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/portgroups",
   965  				Rel:  "self",
   966  			},
   967  			{
   968  				Href: "http://ironic.example.com:6385/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/portgroups",
   969  				Rel:  "bookmark"},
   970  		},
   971  		States: []nodes.Link{
   972  			{
   973  				Href: "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/states",
   974  				Rel:  "self",
   975  			},
   976  		},
   977  		ResourceClass:       "",
   978  		BIOSInterface:       "no-bios",
   979  		BootInterface:       "pxe",
   980  		ConsoleInterface:    "no-console",
   981  		DeployInterface:     "iscsi",
   982  		InspectInterface:    "no-inspect",
   983  		ManagementInterface: "ipmitool",
   984  		NetworkInterface:    "flat",
   985  		PowerInterface:      "ipmitool",
   986  		RAIDInterface:       "no-raid",
   987  		RescueInterface:     "no-rescue",
   988  		StorageInterface:    "noop",
   989  		Traits:              []string{},
   990  		VendorInterface:     "ipmitool",
   991  		Volume: []nodes.Link{
   992  			{
   993  				Href: "http://ironic.example.com:6385/v1/nodes/d2630783-6ec8-4836-b556-ab427c4b581e/volume",
   994  				Rel:  "self",
   995  			},
   996  		},
   997  		ConductorGroup:       "",
   998  		ParentNode:           "",
   999  		Protected:            false,
  1000  		ProtectedReason:      "",
  1001  		Owner:                "",
  1002  		Lessee:               "",
  1003  		Shard:                "",
  1004  		Description:          "",
  1005  		Conductor:            "",
  1006  		AllocationUUID:       "",
  1007  		Retired:              false,
  1008  		RetiredReason:        "No longer needed",
  1009  		NetworkData:          map[string]interface{}(nil),
  1010  		AutomatedClean:       nil,
  1011  		ServiceStep:          map[string]interface{}(nil),
  1012  		FirmwareInterface:    "no-firmware",
  1013  		ProvisionUpdatedAt:   provisonUpdatedAt,
  1014  		InspectionStartedAt:  nil,
  1015  		InspectionFinishedAt: nil,
  1016  		CreatedAt:            createdAtFoo,
  1017  		UpdatedAt:            updatedAt,
  1018  	}
  1019  
  1020  	NodeFooValidation = nodes.NodeValidation{
  1021  		BIOS: nodes.DriverValidation{
  1022  			Result: false,
  1023  			Reason: "Driver ipmi does not support bios (disabled or not implemented).",
  1024  		},
  1025  		Boot: nodes.DriverValidation{
  1026  			Result: false,
  1027  			Reason: "Cannot validate image information for node a62b8495-52e2-407b-b3cb-62775d04c2b8 because one or more parameters are missing from its instance_info and insufficent information is present to boot from a remote volume. Missing are: ['ramdisk', 'kernel', 'image_source']",
  1028  		},
  1029  		Console: nodes.DriverValidation{
  1030  			Result: false,
  1031  			Reason: "Driver ipmi does not support console (disabled or not implemented).",
  1032  		},
  1033  		Deploy: nodes.DriverValidation{
  1034  			Result: false,
  1035  			Reason: "Cannot validate image information for node a62b8495-52e2-407b-b3cb-62775d04c2b8 because one or more parameters are missing from its instance_info and insufficent information is present to boot from a remote volume. Missing are: ['ramdisk', 'kernel', 'image_source']",
  1036  		},
  1037  		Firmware: nodes.DriverValidation{
  1038  			Result: false,
  1039  			Reason: "Driver ipmi does not support firmware (disabled or not implemented).",
  1040  		},
  1041  		Inspect: nodes.DriverValidation{
  1042  			Result: false,
  1043  			Reason: "Driver ipmi does not support inspect (disabled or not implemented).",
  1044  		},
  1045  		Management: nodes.DriverValidation{
  1046  			Result: true,
  1047  		},
  1048  		Network: nodes.DriverValidation{
  1049  			Result: true,
  1050  		},
  1051  		Power: nodes.DriverValidation{
  1052  			Result: true,
  1053  		},
  1054  		RAID: nodes.DriverValidation{
  1055  			Result: false,
  1056  			Reason: "Driver ipmi does not support raid (disabled or not implemented).",
  1057  		},
  1058  		Rescue: nodes.DriverValidation{
  1059  			Result: false,
  1060  			Reason: "Driver ipmi does not support rescue (disabled or not implemented).",
  1061  		},
  1062  		Storage: nodes.DriverValidation{
  1063  			Result: true,
  1064  		},
  1065  	}
  1066  
  1067  	NodeBootDevice = nodes.BootDeviceOpts{
  1068  		BootDevice: "pxe",
  1069  		Persistent: false,
  1070  	}
  1071  
  1072  	NodeSupportedBootDevice = []string{
  1073  		"pxe",
  1074  		"disk",
  1075  	}
  1076  
  1077  	InspectionStartedAt  = time.Date(2023, time.February, 2, 14, 35, 59, 682403000, time.UTC)
  1078  	InspectionFinishedAt = time.Date(2023, time.February, 2, 14, 45, 59, 705249000, time.UTC)
  1079  
  1080  	NodeBar = nodes.Node{
  1081  		UUID:                 "08c84581-58f5-4ea2-a0c6-dd2e5d2b3662",
  1082  		Name:                 "bar",
  1083  		PowerState:           "",
  1084  		TargetPowerState:     "",
  1085  		ProvisionState:       "available",
  1086  		TargetProvisionState: "",
  1087  		Maintenance:          false,
  1088  		MaintenanceReason:    "",
  1089  		Fault:                "",
  1090  		LastError:            "",
  1091  		Reservation:          "",
  1092  		Driver:               "ipmi",
  1093  		DriverInfo:           map[string]any{},
  1094  		DriverInternalInfo:   map[string]any{},
  1095  		Properties:           map[string]any{},
  1096  		InstanceInfo:         map[string]any{},
  1097  		InstanceUUID:         "",
  1098  		ChassisUUID:          "",
  1099  		Extra:                map[string]any{},
  1100  		ConsoleEnabled:       false,
  1101  		RAIDConfig:           map[string]any{},
  1102  		TargetRAIDConfig:     map[string]any{},
  1103  		CleanStep:            map[string]any{},
  1104  		DeployStep:           map[string]any{},
  1105  		ResourceClass:        "",
  1106  		BIOSInterface:        "no-bios",
  1107  		BootInterface:        "pxe",
  1108  		ConsoleInterface:     "no-console",
  1109  		DeployInterface:      "iscsi",
  1110  		FirmwareInterface:    "no-firmware",
  1111  		InspectInterface:     "no-inspect",
  1112  		ManagementInterface:  "ipmitool",
  1113  		NetworkInterface:     "flat",
  1114  		PowerInterface:       "ipmitool",
  1115  		RAIDInterface:        "no-raid",
  1116  		RescueInterface:      "no-rescue",
  1117  		StorageInterface:     "noop",
  1118  		Traits:               []string{},
  1119  		VendorInterface:      "ipmitool",
  1120  		ConductorGroup:       "",
  1121  		Protected:            false,
  1122  		ProtectedReason:      "",
  1123  		CreatedAt:            createdAtBar,
  1124  		UpdatedAt:            updatedAt,
  1125  		InspectionStartedAt:  &InspectionStartedAt,
  1126  		InspectionFinishedAt: &InspectionFinishedAt,
  1127  		Retired:              false,
  1128  		RetiredReason:        "No longer needed",
  1129  		DisablePowerOff:      false,
  1130  		Links: []nodes.Link{
  1131  			{Href: "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662", Rel: "self"},
  1132  			{Href: "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662", Rel: "bookmark"},
  1133  		},
  1134  		Ports: []nodes.Link{
  1135  			{Href: "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/ports", Rel: "self"},
  1136  			{Href: "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/ports", Rel: "bookmark"},
  1137  		},
  1138  		PortGroups: []nodes.Link{
  1139  			{Href: "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/portgroups", Rel: "self"},
  1140  			{Href: "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/portgroups", Rel: "bookmark"},
  1141  		},
  1142  		States: []nodes.Link{
  1143  			{Href: "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/states", Rel: "self"},
  1144  			{Href: "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/states", Rel: "bookmark"},
  1145  		},
  1146  		Volume: []nodes.Link{
  1147  			{Href: "http://ironic.example.com:6385/v1/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/volume", Rel: "self"},
  1148  			{Href: "http://ironic.example.com:6385/nodes/08c84581-58f5-4ea2-a0c6-dd2e5d2b3662/volume", Rel: "bookmark"},
  1149  		},
  1150  	}
  1151  
  1152  	NodeBaz = nodes.Node{
  1153  		UUID:                 "c9afd385-5d89-4ecb-9e1c-68194da6b474",
  1154  		Name:                 "baz",
  1155  		PowerState:           "",
  1156  		TargetPowerState:     "",
  1157  		ProvisionState:       "enroll",
  1158  		TargetProvisionState: "",
  1159  		Maintenance:          false,
  1160  		MaintenanceReason:    "",
  1161  		Fault:                "",
  1162  		LastError:            "",
  1163  		Reservation:          "",
  1164  		Driver:               "ipmi",
  1165  		DriverInfo:           map[string]any{},
  1166  		DriverInternalInfo:   map[string]any{},
  1167  		Properties:           map[string]any{},
  1168  		InstanceInfo:         map[string]any{},
  1169  		InstanceUUID:         "",
  1170  		ChassisUUID:          "",
  1171  		Extra:                map[string]any{},
  1172  		ConsoleEnabled:       false,
  1173  		RAIDConfig:           map[string]any{},
  1174  		TargetRAIDConfig:     map[string]any{},
  1175  		CleanStep:            map[string]any{},
  1176  		DeployStep:           map[string]any{},
  1177  		ResourceClass:        "",
  1178  		BIOSInterface:        "no-bios",
  1179  		BootInterface:        "pxe",
  1180  		ConsoleInterface:     "no-console",
  1181  		DeployInterface:      "iscsi",
  1182  		FirmwareInterface:    "no-firmware",
  1183  		InspectInterface:     "no-inspect",
  1184  		ManagementInterface:  "ipmitool",
  1185  		NetworkInterface:     "flat",
  1186  		PowerInterface:       "ipmitool",
  1187  		RAIDInterface:        "no-raid",
  1188  		RescueInterface:      "no-rescue",
  1189  		StorageInterface:     "noop",
  1190  		Traits:               []string{},
  1191  		VendorInterface:      "ipmitool",
  1192  		ConductorGroup:       "",
  1193  		Protected:            false,
  1194  		ProtectedReason:      "",
  1195  		CreatedAt:            createdAtBaz,
  1196  		UpdatedAt:            updatedAt,
  1197  		Retired:              false,
  1198  		RetiredReason:        "No longer needed",
  1199  		DisablePowerOff:      true,
  1200  		Links: []nodes.Link{
  1201  			{Href: "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474", Rel: "self"},
  1202  			{Href: "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474", Rel: "bookmark"},
  1203  		},
  1204  		Ports: []nodes.Link{
  1205  			{Href: "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/ports", Rel: "self"},
  1206  			{Href: "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/ports", Rel: "bookmark"},
  1207  		},
  1208  		PortGroups: []nodes.Link{
  1209  			{Href: "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/portgroups", Rel: "self"},
  1210  			{Href: "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/portgroups", Rel: "bookmark"},
  1211  		},
  1212  		States: []nodes.Link{
  1213  			{Href: "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/states", Rel: "self"},
  1214  			{Href: "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/states", Rel: "bookmark"},
  1215  		},
  1216  		Volume: []nodes.Link{
  1217  			{Href: "http://ironic.example.com:6385/v1/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/volume", Rel: "self"},
  1218  			{Href: "http://ironic.example.com:6385/nodes/c9afd385-5d89-4ecb-9e1c-68194da6b474/volume", Rel: "bookmark"},
  1219  		},
  1220  	}
  1221  
  1222  	ConfigDriveMap = nodes.ConfigDrive{
  1223  		UserData: map[string]any{
  1224  			"ignition": map[string]string{
  1225  				"version": "2.2.0",
  1226  			},
  1227  			"systemd": map[string]any{
  1228  				"units": []map[string]any{{
  1229  					"name":    "example.service",
  1230  					"enabled": true,
  1231  				},
  1232  				},
  1233  			},
  1234  		},
  1235  	}
  1236  
  1237  	NodeBIOSSettings = []nodes.BIOSSetting{
  1238  		{
  1239  			Name:  "Proc1L2Cache",
  1240  			Value: "10x256 KB",
  1241  		},
  1242  		{
  1243  			Name:  "Proc1NumCores",
  1244  			Value: "10",
  1245  		},
  1246  		{
  1247  			Name:  "ProcVirtualization",
  1248  			Value: "Enabled",
  1249  		},
  1250  	}
  1251  
  1252  	iTrue      = true
  1253  	iFalse     = false
  1254  	minLength  = 0
  1255  	maxLength  = 16
  1256  	lowerBound = 0
  1257  	upperBound = 20
  1258  
  1259  	NodeDetailBIOSSettings = []nodes.BIOSSetting{
  1260  		{
  1261  			Name:            "Proc1L2Cache",
  1262  			Value:           "10x256 KB",
  1263  			AttributeType:   "String",
  1264  			AllowableValues: []string{},
  1265  			LowerBound:      nil,
  1266  			UpperBound:      nil,
  1267  			MinLength:       &minLength,
  1268  			MaxLength:       &maxLength,
  1269  			ReadOnly:        &iTrue,
  1270  			ResetRequired:   nil,
  1271  			Unique:          nil,
  1272  		},
  1273  		{
  1274  			Name:            "Proc1NumCores",
  1275  			Value:           "10",
  1276  			AttributeType:   "Integer",
  1277  			AllowableValues: []string{},
  1278  			LowerBound:      &lowerBound,
  1279  			UpperBound:      &upperBound,
  1280  			MinLength:       nil,
  1281  			MaxLength:       nil,
  1282  			ReadOnly:        &iTrue,
  1283  			ResetRequired:   nil,
  1284  			Unique:          nil,
  1285  		},
  1286  		{
  1287  			Name:            "ProcVirtualization",
  1288  			Value:           "Enabled",
  1289  			AttributeType:   "Enumeration",
  1290  			AllowableValues: []string{"Enabled", "Disabled"},
  1291  			LowerBound:      nil,
  1292  			UpperBound:      nil,
  1293  			MinLength:       nil,
  1294  			MaxLength:       nil,
  1295  			ReadOnly:        &iFalse,
  1296  			ResetRequired:   nil,
  1297  			Unique:          nil,
  1298  		},
  1299  	}
  1300  
  1301  	NodeSingleBIOSSetting = nodes.BIOSSetting{
  1302  		Name:  "ProcVirtualization",
  1303  		Value: "Enabled",
  1304  	}
  1305  
  1306  	NodeVendorPassthruMethods = nodes.VendorPassthruMethods{
  1307  		CreateSubscription: nodes.CreateSubscriptionMethod{
  1308  			HTTPMethods:          []string{"POST"},
  1309  			Async:                false,
  1310  			Description:          "",
  1311  			Attach:               false,
  1312  			RequireExclusiveLock: true,
  1313  		},
  1314  		DeleteSubscription: nodes.DeleteSubscriptionMethod{
  1315  			HTTPMethods:          []string{"DELETE"},
  1316  			Async:                false,
  1317  			Description:          "",
  1318  			Attach:               false,
  1319  			RequireExclusiveLock: true,
  1320  		},
  1321  		GetSubscription: nodes.GetSubscriptionMethod{
  1322  			HTTPMethods:          []string{"GET"},
  1323  			Async:                false,
  1324  			Description:          "",
  1325  			Attach:               false,
  1326  			RequireExclusiveLock: true,
  1327  		},
  1328  		GetAllSubscriptions: nodes.GetAllSubscriptionsMethod{
  1329  			HTTPMethods:          []string{"GET"},
  1330  			Async:                false,
  1331  			Description:          "",
  1332  			Attach:               false,
  1333  			RequireExclusiveLock: true,
  1334  		},
  1335  	}
  1336  
  1337  	NodeGetAllSubscriptions = nodes.GetAllSubscriptionsVendorPassthru{
  1338  		Context:      "/redfish/v1/$metadata#EventDestinationCollection.EventDestinationCollection",
  1339  		Etag:         "",
  1340  		Id:           "/redfish/v1/EventService/Subscriptions",
  1341  		Type:         "#EventDestinationCollection.EventDestinationCollection",
  1342  		Description:  "List of Event subscriptions",
  1343  		Name:         "Event Subscriptions Collection",
  1344  		Members:      []map[string]string{{"@odata.id": "/redfish/v1/EventService/Subscriptions/62dbd1b6-f637-11eb-b551-4cd98f20754c"}},
  1345  		MembersCount: 1,
  1346  	}
  1347  
  1348  	NodeGetSubscription = nodes.SubscriptionVendorPassthru{
  1349  		Id:          "62dbd1b6-f637-11eb-b551-4cd98f20754c",
  1350  		Context:     "Ironic",
  1351  		Destination: "https://192.168.0.1/EventReceiver.php",
  1352  		EventTypes:  []string{"Alert"},
  1353  		Protocol:    "Redfish",
  1354  	}
  1355  
  1356  	NodeCreateSubscriptionRequiredParameters = nodes.SubscriptionVendorPassthru{
  1357  		Id:          "344a3e2-978a-444e-990a-cbf47c62ef88",
  1358  		Context:     "",
  1359  		Destination: "https://somedestinationurl",
  1360  		EventTypes:  []string{"Alert"},
  1361  		Protocol:    "Redfish",
  1362  	}
  1363  
  1364  	NodeCreateSubscriptionAllParameters = nodes.SubscriptionVendorPassthru{
  1365  		Id:          "eaa43e2-018a-424e-990a-cbf47c62ef80",
  1366  		Context:     "gophercloud",
  1367  		Destination: "https://someurl",
  1368  		EventTypes:  []string{"Alert"},
  1369  		Protocol:    "Redfish",
  1370  	}
  1371  
  1372  	NodeInventoryData = nodes.InventoryData{
  1373  		Inventory: inventorytest.Inventory,
  1374  	}
  1375  
  1376  	createdAtFirmware, _ = time.Parse(time.RFC3339, "2023-10-03T18:30:00+00:00")
  1377  	updatedAtFirmware, _ = time.Parse(time.RFC3339, "2023-10-03T18:45:54+00:00")
  1378  	lastVersion          = "iLO 5 v2.81"
  1379  	NodeFirmwareList     = []nodes.FirmwareComponent{
  1380  		{
  1381  			CreatedAt:          createdAtFirmware,
  1382  			UpdatedAt:          nil,
  1383  			Component:          "bios",
  1384  			InitialVersion:     "U30 v2.36 (07/16/2020)",
  1385  			CurrentVersion:     "U30 v2.36 (07/16/2020)",
  1386  			LastVersionFlashed: "",
  1387  		},
  1388  		{
  1389  			CreatedAt:          createdAtFirmware,
  1390  			UpdatedAt:          &updatedAtFirmware,
  1391  			Component:          "bmc",
  1392  			InitialVersion:     "iLO 5 v2.78",
  1393  			CurrentVersion:     "iLO 5 v2.81",
  1394  			LastVersionFlashed: lastVersion,
  1395  		},
  1396  	}
  1397  )
  1398  
  1399  // HandleNodeListSuccessfully sets up the test server to respond to a server List request.
  1400  func HandleNodeListSuccessfully(t *testing.T) {
  1401  	th.Mux.HandleFunc("/nodes", func(w http.ResponseWriter, r *http.Request) {
  1402  		th.TestMethod(t, r, "GET")
  1403  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1404  		w.Header().Add("Content-Type", "application/json")
  1405  		if err := r.ParseForm(); err != nil {
  1406  			t.Errorf("Failed to parse request form %v", err)
  1407  		}
  1408  
  1409  		marker := r.Form.Get("marker")
  1410  		switch marker {
  1411  		case "":
  1412  			fmt.Fprint(w, NodeListBody)
  1413  
  1414  		case "9e5476bd-a4ec-4653-93d6-72c93aa682ba":
  1415  			fmt.Fprint(w, `{ "servers": [] }`)
  1416  		default:
  1417  			t.Fatalf("/nodes invoked with unexpected marker=[%s]", marker)
  1418  		}
  1419  	})
  1420  }
  1421  
  1422  // HandleNodeListSuccessfully sets up the test server to respond to a server List request.
  1423  func HandleNodeListDetailSuccessfully(t *testing.T) {
  1424  	th.Mux.HandleFunc("/nodes/detail", func(w http.ResponseWriter, r *http.Request) {
  1425  		th.TestMethod(t, r, "GET")
  1426  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1427  		w.Header().Add("Content-Type", "application/json")
  1428  		if err := r.ParseForm(); err != nil {
  1429  			t.Errorf("Failed to parse request form %v", err)
  1430  		}
  1431  
  1432  		fmt.Fprint(w, NodeListDetailBody)
  1433  	})
  1434  }
  1435  
  1436  // HandleServerCreationSuccessfully sets up the test server to respond to a server creation request
  1437  // with a given response.
  1438  func HandleNodeCreationSuccessfully(t *testing.T, response string) {
  1439  	th.Mux.HandleFunc("/nodes", func(w http.ResponseWriter, r *http.Request) {
  1440  		th.TestMethod(t, r, "POST")
  1441  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1442  		th.TestJSONRequest(t, r, `{
  1443            "boot_interface": "pxe",
  1444            "driver": "ipmi",
  1445            "driver_info": {
  1446              "deploy_kernel": "http://172.22.0.1/images/tinyipa-stable-rocky.vmlinuz",
  1447              "deploy_ramdisk": "http://172.22.0.1/images/tinyipa-stable-rocky.gz",
  1448              "ipmi_address": "192.168.122.1",
  1449              "ipmi_password": "admin",
  1450              "ipmi_port": "6230",
  1451              "ipmi_username": "admin"
  1452            },
  1453            "firmware_interface": "no-firmware",
  1454            "name": "foo"
  1455          }`)
  1456  
  1457  		w.WriteHeader(http.StatusAccepted)
  1458  		w.Header().Add("Content-Type", "application/json")
  1459  		fmt.Fprint(w, response)
  1460  	})
  1461  }
  1462  
  1463  // HandleNodeDeletionSuccessfully sets up the test server to respond to a server deletion request.
  1464  func HandleNodeDeletionSuccessfully(t *testing.T) {
  1465  	th.Mux.HandleFunc("/nodes/asdfasdfasdf", func(w http.ResponseWriter, r *http.Request) {
  1466  		th.TestMethod(t, r, "DELETE")
  1467  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1468  
  1469  		w.WriteHeader(http.StatusNoContent)
  1470  	})
  1471  }
  1472  
  1473  func HandleNodeGetSuccessfully(t *testing.T) {
  1474  	th.Mux.HandleFunc("/nodes/1234asdf", func(w http.ResponseWriter, r *http.Request) {
  1475  		th.TestMethod(t, r, "GET")
  1476  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1477  		th.TestHeader(t, r, "Accept", "application/json")
  1478  
  1479  		fmt.Fprint(w, SingleNodeBody)
  1480  	})
  1481  }
  1482  
  1483  func HandleNodeUpdateSuccessfully(t *testing.T, response string) {
  1484  	th.Mux.HandleFunc("/nodes/1234asdf", func(w http.ResponseWriter, r *http.Request) {
  1485  		th.TestMethod(t, r, "PATCH")
  1486  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1487  		th.TestHeader(t, r, "Accept", "application/json")
  1488  		th.TestHeader(t, r, "Content-Type", "application/json")
  1489  		th.TestJSONRequest(t, r, `[{"op": "replace", "path": "/properties", "value": {"root_gb": 25}}]`)
  1490  
  1491  		fmt.Fprint(w, response)
  1492  	})
  1493  }
  1494  
  1495  func HandleNodeValidateSuccessfully(t *testing.T) {
  1496  	th.Mux.HandleFunc("/nodes/1234asdf/validate", func(w http.ResponseWriter, r *http.Request) {
  1497  		th.TestMethod(t, r, "GET")
  1498  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1499  		th.TestHeader(t, r, "Accept", "application/json")
  1500  
  1501  		fmt.Fprint(w, NodeValidationBody)
  1502  	})
  1503  }
  1504  
  1505  // HandleInjectNMISuccessfully sets up the test server to respond to a node InjectNMI request
  1506  func HandleInjectNMISuccessfully(t *testing.T) {
  1507  	th.Mux.HandleFunc("/nodes/1234asdf/management/inject_nmi", func(w http.ResponseWriter, r *http.Request) {
  1508  		th.TestMethod(t, r, "PUT")
  1509  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1510  		th.TestJSONRequest(t, r, "{}")
  1511  
  1512  		w.WriteHeader(http.StatusNoContent)
  1513  	})
  1514  }
  1515  
  1516  // HandleSetBootDeviceSuccessfully sets up the test server to respond to a set boot device request for a node
  1517  func HandleSetBootDeviceSuccessfully(t *testing.T) {
  1518  	th.Mux.HandleFunc("/nodes/1234asdf/management/boot_device", func(w http.ResponseWriter, r *http.Request) {
  1519  		th.TestMethod(t, r, "PUT")
  1520  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1521  		th.TestJSONRequest(t, r, NodeBootDeviceBody)
  1522  
  1523  		w.WriteHeader(http.StatusNoContent)
  1524  	})
  1525  }
  1526  
  1527  // HandleGetBootDeviceSuccessfully sets up the test server to respond to a get boot device request for a node
  1528  func HandleGetBootDeviceSuccessfully(t *testing.T) {
  1529  	th.Mux.HandleFunc("/nodes/1234asdf/management/boot_device", func(w http.ResponseWriter, r *http.Request) {
  1530  		th.TestMethod(t, r, "GET")
  1531  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1532  		w.WriteHeader(http.StatusOK)
  1533  		fmt.Fprint(w, NodeBootDeviceBody)
  1534  	})
  1535  }
  1536  
  1537  // HandleGetBootDeviceSuccessfully sets up the test server to respond to a get boot device request for a node
  1538  func HandleGetSupportedBootDeviceSuccessfully(t *testing.T) {
  1539  	th.Mux.HandleFunc("/nodes/1234asdf/management/boot_device/supported", func(w http.ResponseWriter, r *http.Request) {
  1540  		th.TestMethod(t, r, "GET")
  1541  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1542  		w.WriteHeader(http.StatusOK)
  1543  		fmt.Fprint(w, NodeSupportedBootDeviceBody)
  1544  	})
  1545  }
  1546  
  1547  func HandleNodeChangeProvisionStateActive(t *testing.T) {
  1548  	th.Mux.HandleFunc("/nodes/1234asdf/states/provision", func(w http.ResponseWriter, r *http.Request) {
  1549  		th.TestMethod(t, r, "PUT")
  1550  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1551  		th.TestJSONRequest(t, r, NodeProvisionStateActiveBody)
  1552  		w.WriteHeader(http.StatusAccepted)
  1553  	})
  1554  }
  1555  
  1556  func HandleNodeChangeProvisionStateActiveWithSteps(t *testing.T) {
  1557  	th.Mux.HandleFunc("/nodes/1234asdf/states/provision", func(w http.ResponseWriter, r *http.Request) {
  1558  		th.TestMethod(t, r, "PUT")
  1559  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1560  		th.TestJSONRequest(t, r, NodeProvisionStateActiveBodyWithSteps)
  1561  		w.WriteHeader(http.StatusAccepted)
  1562  	})
  1563  }
  1564  
  1565  func HandleNodeChangeProvisionStateClean(t *testing.T) {
  1566  	th.Mux.HandleFunc("/nodes/1234asdf/states/provision", func(w http.ResponseWriter, r *http.Request) {
  1567  		th.TestMethod(t, r, "PUT")
  1568  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1569  		th.TestJSONRequest(t, r, NodeProvisionStateCleanBody)
  1570  		w.WriteHeader(http.StatusAccepted)
  1571  	})
  1572  }
  1573  
  1574  func HandleNodeChangeProvisionStateCleanWithConflict(t *testing.T) {
  1575  	th.Mux.HandleFunc("/nodes/1234asdf/states/provision", func(w http.ResponseWriter, r *http.Request) {
  1576  		th.TestMethod(t, r, "PUT")
  1577  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1578  		th.TestJSONRequest(t, r, NodeProvisionStateCleanBody)
  1579  		w.WriteHeader(http.StatusConflict)
  1580  	})
  1581  }
  1582  
  1583  func HandleNodeChangeProvisionStateConfigDrive(t *testing.T) {
  1584  	th.Mux.HandleFunc("/nodes/1234asdf/states/provision", func(w http.ResponseWriter, r *http.Request) {
  1585  		th.TestMethod(t, r, "PUT")
  1586  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1587  		th.TestJSONRequest(t, r, NodeProvisionStateConfigDriveBody)
  1588  		w.WriteHeader(http.StatusAccepted)
  1589  	})
  1590  }
  1591  
  1592  func HandleNodeChangeProvisionStateService(t *testing.T) {
  1593  	th.Mux.HandleFunc("/nodes/1234asdf/states/provision", func(w http.ResponseWriter, r *http.Request) {
  1594  		th.TestMethod(t, r, "PUT")
  1595  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1596  		th.TestJSONRequest(t, r, NodeProvisionStateServiceBody)
  1597  		w.WriteHeader(http.StatusAccepted)
  1598  	})
  1599  }
  1600  
  1601  // HandleChangePowerStateSuccessfully sets up the test server to respond to a change power state request for a node
  1602  func HandleChangePowerStateSuccessfully(t *testing.T) {
  1603  	th.Mux.HandleFunc("/nodes/1234asdf/states/power", func(w http.ResponseWriter, r *http.Request) {
  1604  		th.TestMethod(t, r, "PUT")
  1605  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1606  		th.TestJSONRequest(t, r, `{
  1607  			"target": "power on",
  1608  			"timeout": 100
  1609  		}`)
  1610  
  1611  		w.WriteHeader(http.StatusAccepted)
  1612  	})
  1613  }
  1614  
  1615  // HandleChangePowerStateWithConflict sets up the test server to respond to a change power state request for a node with a 409 error
  1616  func HandleChangePowerStateWithConflict(t *testing.T) {
  1617  	th.Mux.HandleFunc("/nodes/1234asdf/states/power", func(w http.ResponseWriter, r *http.Request) {
  1618  		th.TestMethod(t, r, "PUT")
  1619  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1620  		th.TestJSONRequest(t, r, `{
  1621  			"target": "power on",
  1622  			"timeout": 100
  1623  		}`)
  1624  
  1625  		w.WriteHeader(http.StatusConflict)
  1626  	})
  1627  }
  1628  
  1629  func HandleSetRAIDConfig(t *testing.T) {
  1630  	th.Mux.HandleFunc("/nodes/1234asdf/states/raid", func(w http.ResponseWriter, r *http.Request) {
  1631  		th.TestMethod(t, r, "PUT")
  1632  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1633  		th.TestJSONRequest(t, r, `
  1634  			{
  1635  			   "logical_disks" : [
  1636  				  {
  1637  					 "size_gb" : 100,
  1638  					 "is_root_volume" : true,
  1639  					 "raid_level" : "1"
  1640  				  }
  1641  			   ]
  1642  			}
  1643  		`)
  1644  
  1645  		w.WriteHeader(http.StatusNoContent)
  1646  	})
  1647  }
  1648  
  1649  func HandleSetRAIDConfigMaxSize(t *testing.T) {
  1650  	th.Mux.HandleFunc("/nodes/1234asdf/states/raid", func(w http.ResponseWriter, r *http.Request) {
  1651  		th.TestMethod(t, r, "PUT")
  1652  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1653  		th.TestJSONRequest(t, r, `
  1654  			{
  1655  			   "logical_disks" : [
  1656  				  {
  1657  					 "size_gb" : "MAX",
  1658  					 "is_root_volume" : true,
  1659  					 "raid_level" : "1"
  1660  				  }
  1661  			   ]
  1662  			}
  1663  		`)
  1664  
  1665  		w.WriteHeader(http.StatusNoContent)
  1666  	})
  1667  }
  1668  
  1669  func HandleListBIOSSettingsSuccessfully(t *testing.T) {
  1670  	th.Mux.HandleFunc("/nodes/1234asdf/bios", func(w http.ResponseWriter, r *http.Request) {
  1671  		th.TestMethod(t, r, "GET")
  1672  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1673  		th.TestHeader(t, r, "Accept", "application/json")
  1674  
  1675  		fmt.Fprint(w, NodeBIOSSettingsBody)
  1676  	})
  1677  }
  1678  
  1679  func HandleListDetailBIOSSettingsSuccessfully(t *testing.T) {
  1680  	th.Mux.HandleFunc("/nodes/1234asdf/bios", func(w http.ResponseWriter, r *http.Request) {
  1681  		th.TestMethod(t, r, "GET")
  1682  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1683  		th.TestHeader(t, r, "Accept", "application/json")
  1684  
  1685  		fmt.Fprint(w, NodeDetailBIOSSettingsBody)
  1686  	})
  1687  }
  1688  
  1689  func HandleGetBIOSSettingSuccessfully(t *testing.T) {
  1690  	th.Mux.HandleFunc("/nodes/1234asdf/bios/ProcVirtualization", func(w http.ResponseWriter, r *http.Request) {
  1691  		th.TestMethod(t, r, "GET")
  1692  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1693  		th.TestHeader(t, r, "Accept", "application/json")
  1694  
  1695  		fmt.Fprint(w, NodeSingleBIOSSettingBody)
  1696  	})
  1697  }
  1698  
  1699  func HandleGetVendorPassthruMethodsSuccessfully(t *testing.T) {
  1700  	th.Mux.HandleFunc("/nodes/1234asdf/vendor_passthru/methods", func(w http.ResponseWriter, r *http.Request) {
  1701  		th.TestMethod(t, r, "GET")
  1702  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1703  		th.TestHeader(t, r, "Accept", "application/json")
  1704  
  1705  		fmt.Fprint(w, NodeVendorPassthruMethodsBody)
  1706  	})
  1707  }
  1708  
  1709  func HandleGetAllSubscriptionsVendorPassthruSuccessfully(t *testing.T) {
  1710  	th.Mux.HandleFunc("/nodes/1234asdf/vendor_passthru", func(w http.ResponseWriter, r *http.Request) {
  1711  		th.TestMethod(t, r, "GET")
  1712  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1713  		th.TestHeader(t, r, "Accept", "application/json")
  1714  		th.TestFormValues(t, r, map[string]string{"method": "get_all_subscriptions"})
  1715  
  1716  		fmt.Fprint(w, NodeGetAllSubscriptionsVnedorPassthruBody)
  1717  	})
  1718  }
  1719  
  1720  func HandleGetSubscriptionVendorPassthruSuccessfully(t *testing.T) {
  1721  	th.Mux.HandleFunc("/nodes/1234asdf/vendor_passthru", func(w http.ResponseWriter, r *http.Request) {
  1722  		th.TestMethod(t, r, "GET")
  1723  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1724  		th.TestHeader(t, r, "Accept", "application/json")
  1725  		th.TestFormValues(t, r, map[string]string{"method": "get_subscription"})
  1726  		th.TestJSONRequest(t, r, `
  1727  			{
  1728  			   "id" : "62dbd1b6-f637-11eb-b551-4cd98f20754c"
  1729  			}
  1730  		`)
  1731  
  1732  		fmt.Fprint(w, NodeGetSubscriptionVendorPassthruBody)
  1733  	})
  1734  }
  1735  
  1736  func HandleCreateSubscriptionVendorPassthruAllParametersSuccessfully(t *testing.T) {
  1737  	th.Mux.HandleFunc("/nodes/1234asdf/vendor_passthru", func(w http.ResponseWriter, r *http.Request) {
  1738  		th.TestMethod(t, r, "POST")
  1739  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1740  		th.TestHeader(t, r, "Accept", "application/json")
  1741  		th.TestFormValues(t, r, map[string]string{"method": "create_subscription"})
  1742  		th.TestJSONRequest(t, r, `
  1743  			{
  1744           "Context":      "gophercloud",
  1745           "EventTypes":   ["Alert"],
  1746           "HttpHeaders":  [{"Content-Type":"application/json"}],
  1747           "Protocol":     "Redfish",
  1748  			   "Destination" : "https://someurl"
  1749  			}
  1750  		`)
  1751  
  1752  		fmt.Fprint(w, NodeCreateSubscriptionVendorPassthruAllParametersBody)
  1753  	})
  1754  }
  1755  
  1756  func HandleCreateSubscriptionVendorPassthruRequiredParametersSuccessfully(t *testing.T) {
  1757  	th.Mux.HandleFunc("/nodes/1234asdf/vendor_passthru", func(w http.ResponseWriter, r *http.Request) {
  1758  		th.TestMethod(t, r, "POST")
  1759  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1760  		th.TestHeader(t, r, "Accept", "application/json")
  1761  		th.TestFormValues(t, r, map[string]string{"method": "create_subscription"})
  1762  		th.TestJSONRequest(t, r, `
  1763  			{
  1764  			   "Destination" : "https://somedestinationurl"
  1765  			}
  1766  		`)
  1767  
  1768  		fmt.Fprint(w, NodeCreateSubscriptionVendorPassthruRequiredParametersBody)
  1769  	})
  1770  }
  1771  
  1772  func HandleDeleteSubscriptionVendorPassthruSuccessfully(t *testing.T) {
  1773  	th.Mux.HandleFunc("/nodes/1234asdf/vendor_passthru", func(w http.ResponseWriter, r *http.Request) {
  1774  		th.TestMethod(t, r, "DELETE")
  1775  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1776  		th.TestHeader(t, r, "Accept", "application/json")
  1777  		th.TestFormValues(t, r, map[string]string{"method": "delete_subscription"})
  1778  		th.TestJSONRequest(t, r, `
  1779  			{
  1780  			   "id" : "344a3e2-978a-444e-990a-cbf47c62ef88"
  1781  			}
  1782  		`)
  1783  
  1784  		w.WriteHeader(http.StatusNoContent)
  1785  	})
  1786  }
  1787  
  1788  func HandleSetNodeMaintenanceSuccessfully(t *testing.T) {
  1789  	th.Mux.HandleFunc("/nodes/1234asdf/maintenance", func(w http.ResponseWriter, r *http.Request) {
  1790  		th.TestMethod(t, r, "PUT")
  1791  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1792  		th.TestJSONRequest(t, r, NodeSetMaintenanceBody)
  1793  
  1794  		w.WriteHeader(http.StatusAccepted)
  1795  	})
  1796  }
  1797  
  1798  func HandleUnsetNodeMaintenanceSuccessfully(t *testing.T) {
  1799  	th.Mux.HandleFunc("/nodes/1234asdf/maintenance", func(w http.ResponseWriter, r *http.Request) {
  1800  		th.TestMethod(t, r, "DELETE")
  1801  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1802  
  1803  		w.WriteHeader(http.StatusAccepted)
  1804  	})
  1805  }
  1806  
  1807  // HandleGetInventorySuccessfully sets up the test server to respond to a get inventory request for a node
  1808  func HandleGetInventorySuccessfully(t *testing.T) {
  1809  	th.Mux.HandleFunc("/nodes/1234asdf/inventory", func(w http.ResponseWriter, r *http.Request) {
  1810  		th.TestMethod(t, r, "GET")
  1811  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1812  		w.WriteHeader(http.StatusOK)
  1813  		fmt.Fprint(w, NodeInventoryBody)
  1814  	})
  1815  }
  1816  
  1817  // HandleListFirmware
  1818  func HandleListFirmwareSuccessfully(t *testing.T) {
  1819  	th.Mux.HandleFunc("/nodes/1234asdf/firmware", func(w http.ResponseWriter, r *http.Request) {
  1820  		th.TestMethod(t, r, "GET")
  1821  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1822  		w.WriteHeader(http.StatusOK)
  1823  		fmt.Fprint(w, NodeFirmwareListBody)
  1824  	})
  1825  }
  1826  
  1827  func HandleAttachVirtualMediaSuccessfully(t *testing.T, withSource bool) {
  1828  	th.Mux.HandleFunc("/nodes/1234asdf/vmedia", func(w http.ResponseWriter, r *http.Request) {
  1829  		th.TestMethod(t, r, "POST")
  1830  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1831  		if withSource {
  1832  			th.TestJSONRequest(t, r, NodeVirtualMediaAttachBodyWithSource)
  1833  		} else {
  1834  			th.TestJSONRequest(t, r, NodeVirtualMediaAttachBody)
  1835  		}
  1836  		w.WriteHeader(http.StatusNoContent)
  1837  	})
  1838  }
  1839  
  1840  func HandleDetachVirtualMediaSuccessfully(t *testing.T, withType bool) {
  1841  	th.Mux.HandleFunc("/nodes/1234asdf/vmedia", func(w http.ResponseWriter, r *http.Request) {
  1842  		th.TestMethod(t, r, "DELETE")
  1843  		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
  1844  		if withType {
  1845  			th.TestFormValues(t, r, map[string]string{"device_types": "cdrom"})
  1846  		} else {
  1847  			th.TestFormValues(t, r, map[string]string{})
  1848  		}
  1849  		w.WriteHeader(http.StatusNoContent)
  1850  	})
  1851  }