forked from stmcginnis/gofish
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chassis.go
569 lines (499 loc) · 18.4 KB
/
chassis.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
//
// SPDX-License-Identifier: BSD-3-Clause
//
package redfish
import (
"encoding/json"
"fmt"
"reflect"
"io/ioutil"
"bytes"
"os"
"io"
"strings"
"github.com/ciferlu1024/gofish/common"
)
// ChassisType is a physical form of the chassis
type ChassisType string
const (
// BladeChassisType is an enclosed or semi-enclosed, typically vertically-oriented, system
// chassis which must be plugged into a multi-system chassis to function normally.
BladeChassisType ChassisType = "Blade"
// CardChassisType is a loose device or circuit board intended to be installed in a system
// or other enclosure.
CardChassisType ChassisType = "Card"
// CartridgeChassisType is a small self-contained system intended to be plugged into a multi-system
// chassis.
CartridgeChassisType ChassisType = "Cartridge"
// ComponentChassisType is a small chassis, card, or device which contains devices for a particular
// subsystem or function.
ComponentChassisType ChassisType = "Component"
// DrawerChassisType is an enclosed or semi-enclosed, typically horizontally-oriented, system
// chassis which may be slid into a multi-system chassis.
DrawerChassisType ChassisType = "Drawer"
// EnclosureChassisType is a generic term for a chassis that does not fit any other description.
EnclosureChassisType ChassisType = "Enclosure"
// ExpansionChassisType is a chassis which expands the capabilities or capacity of another
// chassis.
ExpansionChassisType ChassisType = "Expansion"
// IPBasedDriveChassisType is a chassis in a drive form factor with IP-based network connections.
IPBasedDriveChassisType ChassisType = "IPBasedDrive"
// ModuleChassisType is a small, typically removable, chassis or card which contains devices
// for a particular subsystem or function.
ModuleChassisType ChassisType = "Module"
// OtherChassisType is a chassis that does not fit any of these definitions.
OtherChassisType ChassisType = "Other"
// PodChassisType is a collection of equipment racks in a large, likely transportable, container.
PodChassisType ChassisType = "Pod"
// RackChassisType is an equipment rack, typically a 19-inch wide freestanding unit.
RackChassisType ChassisType = "Rack"
// RackGroupChassisType is a group of racks which form a single entity or share infrastructure.
RackGroupChassisType ChassisType = "RackGroup"
// RackMountChassisType is a single system chassis designed specifically for mounting in an
// equipment rack.
RackMountChassisType ChassisType = "RackMount"
// RowChassisType is a collection of equipment racks.
RowChassisType ChassisType = "Row"
// ShelfChassisType is an enclosed or semi-enclosed, typically horizontally-oriented, system
// chassis which must be plugged into a multi-system chassis to function normally.
ShelfChassisType ChassisType = "Shelf"
// SidecarChassisType is a chassis that mates mechanically with another chassis to expand
// its capabilities or capacity.
SidecarChassisType ChassisType = "Sidecar"
// SledChassisType is an enclosed or semi-enclosed, system chassis which must be plugged into
// a multi-system chassis to function normally similar to a blade type chassis.
SledChassisType ChassisType = "Sled"
// StandAloneChassisType is a single, free-standing system, commonly called a tower or desktop
// chassis.
StandAloneChassisType ChassisType = "StandAlone"
// StorageEnclosureChassisType is a chassis which encloses storage.
StorageEnclosureChassisType ChassisType = "StorageEnclosure"
// ZoneChassisType is a logical division or portion of a physical chassis that contains multiple
// devices or systems that cannot be physically separated.
ZoneChassisType ChassisType = "Zone"
)
// EnvironmentalClass is
type EnvironmentalClass string
const (
// A1EnvironmentalClass ASHRAE Environmental Class 'A1'.
A1EnvironmentalClass EnvironmentalClass = "A1"
// A2EnvironmentalClass ASHRAE Environmental Class 'A2'.
A2EnvironmentalClass EnvironmentalClass = "A2"
// A3EnvironmentalClass ASHRAE Environmental Class 'A3'.
A3EnvironmentalClass EnvironmentalClass = "A3"
// A4EnvironmentalClass ASHRAE Environmental Class 'A4'.
A4EnvironmentalClass EnvironmentalClass = "A4"
)
// IntrusionSensor is
type IntrusionSensor string
const (
// NormalIntrusionSensor No abnormal physical security condition is
// detected at this time.
NormalIntrusionSensor IntrusionSensor = "Normal"
// HardwareIntrusionIntrusionSensor A door, lock, or other mechanism
// protecting the internal system hardware from being accessed is
// detected to be in an insecure state.
HardwareIntrusionIntrusionSensor IntrusionSensor = "HardwareIntrusion"
// TamperingDetectedIntrusionSensor Physical tampering of the monitored
// entity is detected.
TamperingDetectedIntrusionSensor IntrusionSensor = "TamperingDetected"
)
// IntrusionSensorReArm is
type IntrusionSensorReArm string
const (
// ManualIntrusionSensorReArm A manual re-arm of this sensor restores it
// to the normal state.
ManualIntrusionSensorReArm IntrusionSensorReArm = "Manual"
// AutomaticIntrusionSensorReArm Because no abnormal physical security
// condition is detected, this sensor is automatically restored to the
// normal state.
AutomaticIntrusionSensorReArm IntrusionSensorReArm = "Automatic"
)
// PhysicalSecurity shall describe the sensor state of the physical
// security.
type PhysicalSecurity struct {
// IntrusionSensor is This property shall represent the state of this
// physical security sensor. Hardware intrusion indicates the internal
// hardware is detected as being accessed in an insecure state.
// Tampering detected indicates the physical tampering of the monitored
// entity is detected.
IntrusionSensor IntrusionSensor
// IntrusionSensorNumber is This property shall contain a numerical
// identifier for this physical security sensor that is unique within
// this resource.
IntrusionSensorNumber int
// IntrusionSensorReArm is This property shall represent the method that
// restores this physical security sensor to the normal state. Manual
// indicates manual re-arm is needed. Automatic indicates the state is
// restored automatically because no abnormal physical security
// conditions are detected.
IntrusionSensorReArm IntrusionSensorReArm
}
// Chassis represents the physical components of a system. This
// resource represents the sheet-metal confined spaces and logical zones such
// as racks, enclosures, chassis and all other containers. Subsystems (like sensors)
// that operate outside of a system's data plane (meaning the resources are not
// accessible to software running on the system) are linked either directly or
// indirectly through this resource.
type Chassis struct {
common.Entity
// ODataContext is the odata context.
ODataContext string `json:"@odata.context"`
// ODataType is the odata type.
ODataType string `json:"@odata.type"`
// AssetTag shall contain an identifying string that
// tracks the chassis for inventory purposes.
AssetTag string
// ChassisType shall indicate the physical form factor
// for the type of chassis.
ChassisType ChassisType
// DepthMm shall represent the depth (length) of the
// chassis, in millimeters, as specified by the manufacturer.
DepthMm float64
// Description provides a description of this resource.
Description string
// linkedDrives shall contain an array of links to resources
// of type Drive that are in this chassis.
linkedDrives []string
// Drives shall contain a link to a resource collection of type DriveCollection.
drives string
// DrivesCount is the number of drives attached to this chassis.
DrivesCount int `json:"Drives@odata.count"`
// EnvironmentalClass shall contain the ASHRAE
// Environmental Class for this chassis, as defined by ASHRAE Thermal
// Guidelines for Data Processing Environments. These classes define
// respective environmental limits that include temperature, relative
// humidity, dew point, and maximum allowable elevation.
EnvironmentalClass EnvironmentalClass
// HeightMm shall represent the height of the chassis,
// in millimeters, as specified by the manufacturer.
HeightMm float64
// IndicatorLED shall contain the indicator light state
// for the indicator light associated with this system.
IndicatorLED common.IndicatorLED
// Location shall contain location information of the
// associated chassis.
Location common.Location
// Manufacturer shall contain the name of the
// organization responsible for producing the chassis. This organization
// might be the entity from whom the chassis is purchased, but this is
// not necessarily true.
Manufacturer string
// Model shall contain the name by which the
// manufacturer generally refers to the chassis.
Model string
// PartNumber shall contain a part number assigned by
// the organization that is responsible for producing or manufacturing
// the chassis.
PartNumber string
// PhysicalSecurity shall contain the sensor state of
// the physical security.
PhysicalSecurity PhysicalSecurity
// PowerState shall contain the power state of the
// chassis.
PowerState PowerState
// SKU shall contain the stock-keeping unit number for
// this chassis.
SKU string
// SerialNumber shall contain a manufacturer-allocated
// number that identifies the chassis.
SerialNumber string
// Status shall contain any status or health properties
// of the resource.
Status common.Status
// UUID shall contain the universal unique identifier
// number for this chassis.
UUID string
// WeightKg shall represent the published mass, commonly
// referred to as weight, of the chassis, in kilograms.
WeightKg float64
// WidthMm shall represent the width of the chassis, in
// millimeters, as specified by the manufacturer.
WidthMm float64
thermal string
power string
networkAdapters string
computerSystems []string
resourceBlocks []string
managedBy []string
// resetTarget is the internal URL to send reset actions to.
resetTarget string
// SupportedResetTypes, if provided, is the reset types this chassis supports.
SupportedResetTypes []ResetType
// rawData holds the original serialized JSON so we can compare updates.
rawData []byte
}
// UnmarshalJSON unmarshals a Chassis object from the raw JSON.
func (chassis *Chassis) UnmarshalJSON(b []byte) error {
type temp Chassis
type linkReference struct {
ComputerSystems common.Links
ResourceBlocks common.Links
ManagedBy common.Links
Drives common.Links
DrivesCount int `json:"Drives@odata.count"`
}
type Actions struct {
ChassisReset struct {
AllowedResetTypes []ResetType `json:"ResetType@Redfish.AllowableValues"`
Target string
} `json:"#Chassis.Reset"`
}
var t struct {
temp
Drives common.Link
Thermal common.Link
Power common.Link
NetworkAdapters common.Link
Links linkReference
Actions Actions
}
err := json.Unmarshal(b, &t)
if err != nil {
return err
}
*chassis = Chassis(t.temp)
// Extract the links to other entities for later
chassis.drives = string(t.Drives)
chassis.linkedDrives = t.Links.Drives.ToStrings()
if chassis.DrivesCount == 0 && t.Links.DrivesCount > 0 {
chassis.DrivesCount = t.Links.DrivesCount
}
chassis.thermal = string(t.Thermal)
chassis.power = string(t.Power)
chassis.networkAdapters = string(t.NetworkAdapters)
chassis.computerSystems = t.Links.ComputerSystems.ToStrings()
chassis.resourceBlocks = t.Links.ResourceBlocks.ToStrings()
chassis.managedBy = t.Links.ManagedBy.ToStrings()
chassis.resetTarget = t.Actions.ChassisReset.Target
chassis.SupportedResetTypes = t.Actions.ChassisReset.AllowedResetTypes
// This is a read/write object, so we need to save the raw object data for later
chassis.rawData = b
return nil
}
// Update commits updates to this object's properties to the running system.
func (chassis *Chassis) Update() error {
// Get a representation of the object's original state so we can find what
// to update.
original := new(Chassis)
err := original.UnmarshalJSON(chassis.rawData)
if err != nil {
return err
}
readWriteFields := []string{
"AssetTag",
"IndicatorLED",
}
originalElement := reflect.ValueOf(original).Elem()
currentElement := reflect.ValueOf(chassis).Elem()
return chassis.Entity.Update(originalElement, currentElement, readWriteFields)
}
// GetChassis will get a Chassis instance from the Redfish service.
func GetChassis(c common.Client, uri string) (*Chassis, error) {
resp, err := c.Get(uri)
if err != nil {
return nil, err
}else{
}
defer resp.Body.Close()
// os.Stdout 输出原始json内容!
mybodys, _ := ioutil.ReadAll(resp.Body)
var out bytes.Buffer
err = json.Indent(&out, mybodys, "", "\t")
if err != nil {
fmt.Println("**************************chassis json body 报错!", err)
}
//out.WriteTo(os.Stdout)
file, _ := os.Create("/tmp/chassisjson.txt")
defer file.Close()
out.WriteTo(file)
// 读取json文件获取json数据
jsonFile, err := os.Open("/tmp/chassisjson.txt")
if err != nil {
fmt.Println("error opening json file")
}
defer jsonFile.Close()
jsonData, err := ioutil.ReadAll(jsonFile)
if err!= nil {
fmt.Println("error reading json file")
}
// 重新解析json数据
var r interface{}
err = json.Unmarshal(jsonData, &r)
// fmt.Println("r的值:", r)
// 修改json数据部分字段的格式
newbodymap, _ := r.(map[string]interface{})
//fmt.Printf("newbodymap id的值:%v , 类型:%T \n", newbodymap["Id"], newbodymap["Id"])
//fmt.Printf("newbodymap power的值:%v , 类型:%T \n", newbodymap["Power"], newbodymap["Power"])
newbodymap["Id"] = "1"
delete(newbodymap["Power"].(map[string]interface{}), "Health")
//fmt.Printf("newbodymap id的值:%v , 类型:%T \n", newbodymap["Id"], newbodymap["Id"])
//fmt.Printf("newbodymap power的值:%v , 类型:%T \n", newbodymap["Power"], newbodymap["Power"])
newbodyjson, err := json.Marshal(newbodymap)
if err != nil {
fmt.Println("*************newbodyjson err:", err)
}
/*
var out1 bytes.Buffer
err = json.Indent(&out1, newbodyjson, "", "\t")
out1.WriteTo(os.Stdout)
*/
var chassis Chassis
var newjsonreader io.Reader
newjsonreader = strings.NewReader(string(newbodyjson))
//err = json.NewDecoder(resp.Body).Decode(&chassis)
err = json.NewDecoder(newjsonreader).Decode(&chassis)
if err != nil {
return nil, err
}
chassis.SetClient(c)
return &chassis, nil
}
// ListReferencedChassis gets the collection of Chassis from a provided reference.
func ListReferencedChassis(c common.Client, link string) ([]*Chassis, error) {
var result []*Chassis
links, err := common.GetCollection(c, link)
if err != nil {
return result, err
}
collectionError := common.NewCollectionError()
for _, chassisLink := range links.ItemLinks {
chassis, err := GetChassis(c, chassisLink)
if err != nil {
collectionError.Failures[chassisLink] = err
} else {
result = append(result, chassis)
}
}
if collectionError.Empty() {
return result, nil
}
return result, collectionError
}
// Drives gets the drives attached to the storage controllers that this
// resource represents.
func (chassis *Chassis) Drives() ([]*Drive, error) {
var result []*Drive
if chassis.drives == "" && len(chassis.linkedDrives) == 0 {
return result, nil
}
// In version v1.2.0 of the spec, Drives were added to the Chassis.Links
// property. But in v1.14.0 of the spec, Chassis.Drives was added as a
// direct property.
driveLinks := chassis.linkedDrives
if chassis.drives != "" {
drives, err := common.GetCollection(chassis.Client, chassis.drives)
if err != nil {
return nil, err
}
driveLinks = drives.ItemLinks
}
collectionError := common.NewCollectionError()
for _, driveLink := range driveLinks {
drive, err := GetDrive(chassis.Client, driveLink)
if err != nil {
collectionError.Failures[driveLink] = err
} else {
result = append(result, drive)
}
}
if collectionError.Empty() {
return result, nil
}
return result, collectionError
}
// Thermal gets the thermal temperature and cooling information for the chassis
func (chassis *Chassis) Thermal() (*Thermal, error) {
if chassis.thermal == "" {
return nil, nil
}
thermal, err := GetThermal(chassis.Client, chassis.thermal)
if err != nil {
return nil, err
}
return thermal, nil
}
// Power gets the power information for the chassis
func (chassis *Chassis) Power() (*Power, error) {
if chassis.power == "" {
return nil, nil
}
power, err := GetPower(chassis.Client, chassis.power)
if err != nil {
fmt.Println("**********chassis.go Power() 有报错!")
return nil, err
}else{
fmt.Println("**********chassis.go Power() 正常!")
}
return power, nil
}
// ComputerSystems returns the collection of systems from this chassis
func (chassis *Chassis) ComputerSystems() ([]*ComputerSystem, error) {
var result []*ComputerSystem
collectionError := common.NewCollectionError()
for _, uri := range chassis.computerSystems {
cs, err := GetComputerSystem(chassis.Client, uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, cs)
}
}
if collectionError.Empty() {
return result, nil
}
return result, collectionError
}
// ManagedBy gets the collection of managers of this chassis
func (chassis *Chassis) ManagedBy() ([]*Manager, error) {
var result []*Manager
collectionError := common.NewCollectionError()
for _, uri := range chassis.managedBy {
manager, err := GetManager(chassis.Client, uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, manager)
}
}
if collectionError.Empty() {
return result, nil
}
return result, collectionError
}
// NetworkAdapters gets the collection of network adapters of this chassis
func (chassis *Chassis) NetworkAdapters() ([]*NetworkAdapter, error) {
return ListReferencedNetworkAdapter(chassis.Client, chassis.networkAdapters)
}
// Reset shall reset the chassis. This action shall not reset Systems or other
// contained resource, although side effects may occur which affect those resources.
func (chassis *Chassis) Reset(resetType ResetType) error {
// Make sure the requested reset type is supported by the chassis
valid := false
if len(chassis.SupportedResetTypes) > 0 {
for _, allowed := range chassis.SupportedResetTypes {
if resetType == allowed {
valid = true
break
}
}
} else {
// No allowed values supplied, assume we are OK
valid = true
}
if !valid {
return fmt.Errorf("reset type '%s' is not supported by this chassis",
resetType)
}
type temp struct {
ResetType ResetType
}
t := temp{
ResetType: resetType,
}
resp, err := chassis.Client.Post(chassis.resetTarget, t)
if err == nil {
defer resp.Body.Close()
}
return err
}