1
1
package serverservice
2
2
3
3
import (
4
- "context"
5
4
"encoding/json"
6
5
"fmt"
7
6
"strconv"
@@ -505,32 +504,53 @@ func (r *Store) nics(deviceVendor string, nics []*common.NIC) []*serverserviceap
505
504
return nil
506
505
}
507
506
507
+ // NIC port attributes go in here
508
+ nicPortAttrs := []* attributes {}
509
+
510
+ // include NIC firmware attributes
511
+ //
512
+ // NIC port attributes are populated below.
513
+ versionedAttrs := []* versionedAttributes {
514
+ {
515
+ Firmware : c .Firmware ,
516
+ Status : c .Status ,
517
+ },
518
+ }
519
+
508
520
// TODO: fix up duplicate NIC attribute being dropped
509
521
for _ , p := range c .NICPorts {
510
- r .setAttributes (
511
- sc ,
512
- & attributes {
513
- Description : c .Description ,
514
- ProductName : c .ProductName ,
515
- Oem : c .Oem ,
516
- Metadata : c .Metadata ,
517
- PhysicalID : p .PhysicalID ,
518
- BusInfo : p .BusInfo ,
519
- MacAddress : p .MacAddress ,
520
- SpeedBits : p .SpeedBits ,
521
- Capabilities : c .Capabilities ,
522
+ nicPortAttrs = append (nicPortAttrs , & attributes {
523
+ ID : p .ID ,
524
+ Description : c .Description ,
525
+ ProductName : c .ProductName ,
526
+ Oem : c .Oem ,
527
+ Metadata : c .Metadata ,
528
+ PhysicalID : p .PhysicalID ,
529
+ BusInfo : p .BusInfo ,
530
+ MacAddress : p .MacAddress ,
531
+ SpeedBits : p .SpeedBits ,
532
+ Capabilities : c .Capabilities ,
533
+ })
534
+
535
+ if p .Status == nil && p .LinkStatus == "" && p .ActiveLinkTechnology == "" && ! p .AutoNeg && p .MTUSize == 0 {
536
+ continue
537
+ }
538
+ // Store the NIC Port status
539
+ versionedAttrs = append (versionedAttrs , & versionedAttributes {
540
+ NicPortStatus : & nicPortStatus {
541
+ ID : p .ID ,
542
+ MTUSize : p .MTUSize ,
543
+ MacAddress : p .MacAddress ,
544
+ Status : p .Status ,
545
+ LinkStatus : p .LinkStatus ,
546
+ AutoSpeedNegotiation : p .AutoNeg ,
547
+ ActiveLinkTechnology : p .ActiveLinkTechnology ,
522
548
},
523
- )
549
+ } )
524
550
}
525
551
526
- r .setVersionedAttributes (
527
- deviceVendor ,
528
- sc ,
529
- & versionedAttributes {
530
- Firmware : c .Firmware ,
531
- Status : c .Status ,
532
- },
533
- )
552
+ r .setAttributesList (sc , nicPortAttrs )
553
+ r .setVersionedAttributesList (deviceVendor , sc , versionedAttrs )
534
554
535
555
components = append (components , sc )
536
556
}
@@ -804,13 +824,74 @@ type attributes struct {
804
824
Oem bool `json:"oem,omitempty"`
805
825
}
806
826
827
+ // nicPortStatus holds the NIC port status which includes the health status and link status information.
828
+ type nicPortStatus struct {
829
+ * common.Status
830
+ ID string `json:"id,omitempty"`
831
+ MacAddress string `json:"macaddress,omitempty"`
832
+ ActiveLinkTechnology string `json:"active_link_technology,omitempty"`
833
+ LinkStatus string `json:"link_status,omitempty"`
834
+ MTUSize int `json:"mtu_size,omitempty"`
835
+ AutoSpeedNegotiation bool `json:"autospeednegotiation,omitempty"`
836
+ }
837
+
807
838
// versionedAttributes are component attributes to be versioned in server service
808
839
type versionedAttributes struct {
809
- Firmware * common.Firmware `json:"firmware,omitempty"`
810
- Status * common.Status `json:"status,omitempty"`
811
- UUID * uuid.UUID `json:"uuid,omitempty"` // UUID references firmware UUID identified in serverservice based on component/device attributes.
812
- SmartStatus string `json:"smart_status,omitempty"`
813
- Vendor string `json:"vendor,omitempty"`
840
+ Firmware * common.Firmware `json:"firmware,omitempty"`
841
+ Status * common.Status `json:"status,omitempty"`
842
+ NicPortStatus * nicPortStatus `json:"nic_port_status,omitempty"`
843
+ UUID * uuid.UUID `json:"uuid,omitempty"` // UUID references firmware UUID identified in serverservice based on component/device attributes.
844
+ SmartStatus string `json:"smart_status,omitempty"`
845
+ Vendor string `json:"vendor,omitempty"`
846
+ }
847
+
848
+ // setAttributesList updates the given component with the given list of attributes.
849
+ //
850
+ // attributes per component in serverservice have a unique constraint on the component ID, namespace values.
851
+ //
852
+ // so if this method is called twice for the same component, namespace, that attribute will be ignored,
853
+ func (r * Store ) setAttributesList (component * serverserviceapi.ServerComponent , attrs []* attributes ) {
854
+ if len (attrs ) == 0 {
855
+ return
856
+ }
857
+
858
+ // convert attributes to raw json
859
+ data , err := json .Marshal (attrs )
860
+ if err != nil {
861
+ r .logger .WithFields (
862
+ logrus.Fields {
863
+ "slug" : component .ComponentTypeSlug ,
864
+ "kind" : fmt .Sprintf ("%T" , data ),
865
+ "err" : err ,
866
+ }).Warn ("error in conversion of versioned attributes to raw data" )
867
+ }
868
+
869
+ if component .Attributes == nil {
870
+ component .Attributes = []serverserviceapi.Attributes {}
871
+ } else {
872
+ for _ , existingA := range component .Attributes {
873
+ if existingA .Namespace != r .attributeNS {
874
+ continue
875
+ }
876
+
877
+ r .logger .WithFields (
878
+ logrus.Fields {
879
+ "slug" : component .ComponentTypeSlug ,
880
+ "kind" : fmt .Sprintf ("%T" , data ),
881
+ "namespace" : r .attributeNS ,
882
+ }).Warn ("duplicate attribute list on component dropped - this is unexpected." )
883
+
884
+ return
885
+ }
886
+ }
887
+
888
+ component .Attributes = append (
889
+ component .Attributes ,
890
+ serverserviceapi.Attributes {
891
+ Namespace : r .attributeNS ,
892
+ Data : data ,
893
+ },
894
+ )
814
895
}
815
896
816
897
// setAttributes updates the serverservice API component object with the given attributes
@@ -845,7 +926,7 @@ func (r *Store) setAttributes(component *serverserviceapi.ServerComponent, attr
845
926
"slug" : component .ComponentTypeSlug ,
846
927
"kind" : fmt .Sprintf ("%T" , data ),
847
928
"namespace" : r .attributeNS ,
848
- }).Warn ("duplicate attribute on component dropped." )
929
+ }).Warn ("duplicate attribute on component dropped - use setAttributesList() instead ." )
849
930
850
931
return
851
932
}
@@ -860,25 +941,87 @@ func (r *Store) setAttributes(component *serverserviceapi.ServerComponent, attr
860
941
)
861
942
}
862
943
863
- // setVersionedAttributes sets the given attributes on the serverservice server component .
944
+ // setVersionedAttributesList updates the given component with given list of versioned attributes .
864
945
//
865
- // note: versioned attributes has a constraint on the server_component_id, namespace
866
- func (r * Store ) setVersionedAttributes (deviceVendor string , component * serverserviceapi.ServerComponent , vattr * versionedAttributes ) {
867
- ctx := context .TODO ()
946
+ // versioned attributes per component in serverservice have a unique constraint on
947
+ // the component ID, namespace, created_at values.
948
+ // If this method is called twice for the same component, namespace, that versioned attribute will be ignored.
949
+ func (r * Store ) setVersionedAttributesList (deviceVendor string , component * serverserviceapi.ServerComponent , vattrs []* versionedAttributes ) {
950
+ if len (vattrs ) == 0 {
951
+ return
952
+ }
868
953
869
- // add FirmwareData
870
- if vattr .Firmware != nil {
871
- var err error
954
+ // enrich firmware data
955
+ for _ , vattr := range vattrs {
956
+ if vattr .Firmware == nil {
957
+ continue
958
+ }
959
+
960
+ r .enrichFirmwareData (deviceVendor , component .Vendor , vattr )
961
+ }
962
+
963
+ // convert versioned attributes to raw json
964
+ data , err := json .Marshal (vattrs )
965
+ if err != nil {
966
+ r .logger .WithFields (
967
+ logrus.Fields {
968
+ "slug" : component .ComponentTypeSlug ,
969
+ "kind" : fmt .Sprintf ("%T" , data ),
970
+ "err" : err ,
971
+ }).Warn ("error in conversion of versioned attributes to raw data" )
972
+ }
973
+
974
+ // skip empty json data containing just the braces `{}`
975
+ min := 2
976
+ if len (data ) == min {
977
+ return
978
+ }
979
+
980
+ if component .VersionedAttributes == nil {
981
+ component .VersionedAttributes = []serverserviceapi.VersionedAttributes {}
982
+ } else {
983
+ // versioned attributes per component in serverservice have a unique constraint on
984
+ // the component ID, namespace, created_at values.
985
+ //
986
+ // so here we ignore the new attribute with the same namespace, if one already exists.
987
+ for _ , existingVA := range component .VersionedAttributes {
988
+ if existingVA .Namespace != r .versionedAttributeNS {
989
+ continue
990
+ }
872
991
873
- vattr , err = r .addFirmwareData (ctx , deviceVendor , component , vattr )
874
- if err != nil {
875
992
r .logger .WithFields (
876
993
logrus.Fields {
877
- "err" : err ,
878
- }).Warn ("error adding firmware data to versioned attribute" )
994
+ "slug" : component .ComponentTypeSlug ,
995
+ "kind" : fmt .Sprintf ("%T" , data ),
996
+ "namespace" : r .versionedAttributeNS ,
997
+ }).Warn ("duplicate versioned attribute on component dropped - this was unexpected." )
998
+
999
+ return
879
1000
}
880
1001
}
881
1002
1003
+ component .VersionedAttributes = append (
1004
+ component .VersionedAttributes ,
1005
+ serverserviceapi.VersionedAttributes {
1006
+ Namespace : r .versionedAttributeNS ,
1007
+ Data : data ,
1008
+ },
1009
+ )
1010
+ }
1011
+
1012
+ // setVersionedAttributes updates a component with single versioned attribute.
1013
+ //
1014
+ // versioned attributes per component in serverservice have a unique constraint on
1015
+ // the component ID, namespace, created_at values.
1016
+ //
1017
+ // so if this method is called twice for the same component, namespace, that versioned attribute will be ignored,
1018
+ // the caller should invoke setVersionedAttributesList() instead.
1019
+ func (r * Store ) setVersionedAttributes (deviceVendor string , component * serverserviceapi.ServerComponent , vattr * versionedAttributes ) {
1020
+ // add FirmwareData
1021
+ if vattr .Firmware != nil {
1022
+ r .enrichFirmwareData (deviceVendor , component .Vendor , vattr )
1023
+ }
1024
+
882
1025
// convert versioned attributes to raw json
883
1026
data , err := json .Marshal (vattr )
884
1027
if err != nil {
@@ -924,26 +1067,22 @@ func (r *Store) setVersionedAttributes(deviceVendor string, component *serverser
924
1067
)
925
1068
}
926
1069
927
- // addFirmwareData queries ServerService for the firmware version and try to find a matcr.
928
- func (r * Store ) addFirmwareData (ctx context.Context , deviceVendor string , component * serverserviceapi.ServerComponent , vattr * versionedAttributes ) (vatrr * versionedAttributes , err error ) {
1070
+ // enrichFirmwareData queries ServerService for the firmware version and try to find a match.
1071
+ //
1072
+ // the given versionedAttribute object is updated to include the firmware vendor and the serverservice firmware UUID.
1073
+ func (r * Store ) enrichFirmwareData (deviceVendor , componentVendor string , vattr * versionedAttributes ) {
929
1074
// Check in the cache if we have a match by vendor + version
930
- for _ , fw := range r .firmwares [component . Vendor ] {
1075
+ for _ , fw := range r .firmwares [componentVendor ] {
931
1076
if strings .EqualFold (fw .Version , vattr .Firmware .Installed ) {
932
1077
vattr .Vendor = fw .Vendor
933
1078
vattr .UUID = & fw .UUID
934
-
935
- return vattr , nil
936
1079
}
937
1080
}
938
1081
939
1082
for _ , fw := range r .firmwares [deviceVendor ] {
940
1083
if strings .EqualFold (fw .Version , vattr .Firmware .Installed ) {
941
1084
vattr .Vendor = fw .Vendor
942
1085
vattr .UUID = & fw .UUID
943
-
944
- return vattr , nil
945
1086
}
946
1087
}
947
-
948
- return vattr , nil
949
1088
}
0 commit comments