@@ -18,7 +18,13 @@ package host
1818
1919import (
2020 "context"
21+ "fmt"
22+ "regexp"
23+ "strconv"
24+ "strings"
25+ "sync"
2126
27+ "github.com/Mellanox/doca-driver-build/entrypoint/internal/constants"
2228 "github.com/Mellanox/doca-driver-build/entrypoint/internal/utils/cmd"
2329 "github.com/Mellanox/doca-driver-build/entrypoint/internal/wrappers"
2430)
@@ -31,6 +37,17 @@ func New(c cmd.Interface, osWrapper wrappers.OSWrapper) Interface {
3137 }
3238}
3339
40+ // RedhatVersionInfo contains version information for RedHat-based distributions
41+ type RedhatVersionInfo struct {
42+ // MajorVersion is the major version number (e.g., 8, 9)
43+ MajorVersion int
44+ // FullVersion is the complete version string (e.g., "8.4", "9.2")
45+ FullVersion string
46+ // OpenShiftVersion is the OpenShift version if running on RHCOS (e.g., "4.9")
47+ // If empty, this is not RHCOS
48+ OpenShiftVersion string
49+ }
50+
3451// Interface is the interface exposed by the host package.
3552type Interface interface {
3653 // GetOSType returns the name of the operating system as a string.
@@ -42,17 +59,68 @@ type Interface interface {
4259 LsMod (ctx context.Context ) (map [string ]LoadedModule , error )
4360 // RmMod unload the kernel module.
4461 RmMod (ctx context.Context , module string ) error
62+ // GetRedHatVersionInfo parses RedHat version information from /host/etc/os-release
63+ // and returns version details. Should only be called for RedHat-based distributions.
64+ GetRedHatVersionInfo (ctx context.Context ) (* RedhatVersionInfo , error )
4565}
4666
4767type host struct {
4868 cmd cmd.Interface
4969 os wrappers.OSWrapper
70+
71+ // Cache for OS type
72+ osTypeCache struct {
73+ value string
74+ err error
75+ once sync.Once
76+ }
77+
78+ // Cache for RedHat version info
79+ redhatVersionCache struct {
80+ value * RedhatVersionInfo
81+ err error
82+ once sync.Once
83+ }
5084}
5185
5286// GetOSType is the default implementation of the host.Interface.
5387func (h * host ) GetOSType (ctx context.Context ) (string , error ) {
54- // TODO: add implementation
55- return "" , nil
88+ h .osTypeCache .once .Do (func () {
89+ // Read /etc/os-release file to determine OS type
90+ osReleaseContent , err := h .os .ReadFile ("/etc/os-release" )
91+ if err != nil {
92+ h .osTypeCache .err = err
93+ return
94+ }
95+
96+ osReleaseStr := string (osReleaseContent )
97+ osReleaseStr = strings .ToLower (osReleaseStr )
98+
99+ // Check for Ubuntu (case insensitive)
100+ if strings .Contains (osReleaseStr , "ubuntu" ) {
101+ h .osTypeCache .value = constants .OSTypeUbuntu
102+ return
103+ }
104+
105+ // Check for SLES (case insensitive)
106+ if strings .Contains (osReleaseStr , "sles" ) {
107+ h .osTypeCache .value = constants .OSTypeSLES
108+ return
109+ }
110+
111+ // Default to redhat for other distributions (RHEL, CentOS, Fedora, etc.)
112+ h .osTypeCache .value = constants .OSTypeRedHat
113+
114+ // Build the redhatVersionCache for RedHat-based systems
115+ h .buildRedHatVersionCache ()
116+
117+ // Check if this is actually an OpenShift system (has OpenShift version)
118+ if h .redhatVersionCache .value != nil && h .redhatVersionCache .value .OpenShiftVersion != "" {
119+ h .osTypeCache .value = constants .OSTypeOpenShift
120+ }
121+ })
122+
123+ return h .osTypeCache .value , h .osTypeCache .err
56124}
57125
58126// GetDebugInfo is the default implementation of the host.Interface.
@@ -67,7 +135,7 @@ type LoadedModule struct {
67135 Name string
68136 // RefCount amount of refs to the module.
69137 RefCount int
70- // UseBy contains names of the modules that depends on this module.
138+ // UsedBy contains names of the modules that depends on this module.
71139 UsedBy []string
72140}
73141
@@ -83,3 +151,95 @@ func (h *host) RmMod(ctx context.Context, module string) error {
83151 // TODO: add implementation
84152 return nil
85153}
154+
155+ // buildRedHatVersionCache builds the RedHat version cache by parsing /host/etc/os-release
156+ func (h * host ) buildRedHatVersionCache () {
157+ // Read /host/etc/os-release file
158+ osReleaseContent , err := h .os .ReadFile ("/host/etc/os-release" )
159+ if err != nil {
160+ h .redhatVersionCache .err = fmt .Errorf ("failed to read /host/etc/os-release: %w" , err )
161+ return
162+ }
163+
164+ osReleaseStr := string (osReleaseContent )
165+
166+ // Parse the os-release content
167+ versionInfo := & RedhatVersionInfo {}
168+
169+ // Extract ID, VERSION_ID, RHEL_VERSION, and OPENSHIFT_VERSION
170+ var id , versionID , rhelVersion , openshiftVersion string
171+
172+ idMatch := regexp .MustCompile (`(?m)^ID=(.+)$` ).FindStringSubmatch (osReleaseStr )
173+ if len (idMatch ) > 1 {
174+ id = strings .Trim (idMatch [1 ], `"` )
175+ }
176+
177+ versionIDMatch := regexp .MustCompile (`(?m)^VERSION_ID=(.+)$` ).FindStringSubmatch (osReleaseStr )
178+ if len (versionIDMatch ) > 1 {
179+ versionID = strings .Trim (versionIDMatch [1 ], `"` )
180+ }
181+
182+ rhelVersionMatch := regexp .MustCompile (`(?m)^RHEL_VERSION=(.+)$` ).FindStringSubmatch (osReleaseStr )
183+ if len (rhelVersionMatch ) > 1 {
184+ rhelVersion = strings .Trim (rhelVersionMatch [1 ], `"` )
185+ }
186+
187+ openshiftVersionMatch := regexp .MustCompile (`(?m)^OPENSHIFT_VERSION=(.+)$` ).FindStringSubmatch (osReleaseStr )
188+ if len (openshiftVersionMatch ) > 1 {
189+ openshiftVersion = strings .Trim (openshiftVersionMatch [1 ], `"` )
190+ }
191+
192+ if id == "rhcos" {
193+ // This is RHCOS - use OpenShift version logic
194+ if openshiftVersion != "" {
195+ versionInfo .OpenShiftVersion = openshiftVersion
196+ } else {
197+ versionInfo .OpenShiftVersion = versionID
198+ }
199+ if versionInfo .OpenShiftVersion == "" {
200+ versionInfo .OpenShiftVersion = constants .DefaultOpenShiftVersion
201+ }
202+ versionInfo .FullVersion = versionInfo .OpenShiftVersion
203+ } else {
204+ // For RHEL and other RedHat-based distros (CentOS, Fedora, etc.)
205+ versionInfo .FullVersion = rhelVersion
206+ if versionInfo .FullVersion == "" {
207+ versionInfo .FullVersion = versionID
208+ }
209+ if versionInfo .FullVersion == "" {
210+ versionInfo .FullVersion = constants .DefaultRHELVersion
211+ }
212+
213+ // If OPENSHIFT_VERSION is present, this might be RHCOS with ID=rhel
214+ if openshiftVersion != "" {
215+ versionInfo .OpenShiftVersion = openshiftVersion
216+ }
217+ }
218+
219+ // Extract major version from full version
220+ majorVersionStr := strings .Split (versionInfo .FullVersion , "." )[0 ]
221+ majorVersion , err := strconv .Atoi (majorVersionStr )
222+ if err != nil {
223+ h .redhatVersionCache .err = fmt .Errorf ("failed to parse major version from '%s': %w" , versionInfo .FullVersion , err )
224+ return
225+ }
226+ versionInfo .MajorVersion = majorVersion
227+
228+ h .redhatVersionCache .value = versionInfo
229+ }
230+
231+ // GetRedHatVersionInfo is the default implementation of the host.Interface.
232+ func (h * host ) GetRedHatVersionInfo (ctx context.Context ) (* RedhatVersionInfo , error ) {
233+ // First check if this is a RedHat-based system
234+ osType , err := h .GetOSType (ctx )
235+ if err != nil {
236+ return nil , fmt .Errorf ("failed to get OS type: %w" , err )
237+ }
238+
239+ if osType != constants .OSTypeRedHat && osType != constants .OSTypeOpenShift {
240+ return nil , fmt .Errorf ("GetRedHatVersionInfo should only be called for RedHat-based distributions, got: %s" , osType )
241+ }
242+
243+ // Return the cached RedHat version info (built during GetOSType)
244+ return h .redhatVersionCache .value , h .redhatVersionCache .err
245+ }
0 commit comments