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