Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Check BIOS for determining GCE residency. #2577

Merged
merged 1 commit into from
Oct 27, 2023

Conversation

amanda-tarafa
Copy link
Contributor

Closes #2475

@jskeet a few comments on this one:

  • The first commit is the implementation for Linux which is more or less straightforward.
  • The second commit is the implementation for Windows, checking against Windows Management Instrumentation and not the Registry. Checking against WMI is what's recommend internally.

I'm happy to rewrite the second commit using reflection so we don't need the extra System.Management dependency, but then we'd have to ask users to include the dll themselves as we cannot add it conditionally on OS, or at least I haven't found how to do that.

@amanda-tarafa amanda-tarafa requested a review from jskeet October 27, 2023 07:20
@amanda-tarafa amanda-tarafa requested a review from a team as a code owner October 27, 2023 07:20
Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of small comments; happy with the general thrust though. Have scheduled a meeting to chat about some of these bits.

return false;
}

private async static Task<bool> IsGoogleBiosAsync()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: private static async

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
else
{
Logger.Info("GCE residency detection through BIOS checking is only supported in Windows and Linux platforms.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change "in" to "on" maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, better with "on".

bool IsWindows()
{
#if NET45 || NET461
// RuntimeInformation.IsOsPlatform is not available for these targets.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless we're using Mono, I guess? We should probably work out what that will do - so long as it's not disastrous, that's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mistaken with this, RuntimeInformation.IsOsPlatform is supported in NET461. So that only leaves NET45, but that's going away in January because of #2561, so I'm changing this to always return false in NET45.

productName = await streamReader.ReadLineAsync().ConfigureAwait(false);
}
productName = productName?.Trim();
return productName == "Google" || productName == "Google Compute Engine";
Copy link
Collaborator

@jskeet jskeet Oct 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we yet know whether this will be accurate for custom universe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked.

@@ -295,7 +296,11 @@ public static Task<bool> IsRunningOnComputeEngine()
return isRunningOnComputeEngineCached.Value;
}

private static async Task<bool> IsRunningOnComputeEngineNoCache()
private static async Task<bool> IsRunningOnComputeEngineNoCacheAsync() =>
await IsMetadataServerAvailableAsync().ConfigureAwait(false)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the other way round? Possibly something to chat about on a VC - especially if we're going to increase the timeout. (I can see multiple angles to this...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this. Keeping as is for the time being to cause the least disruption to users that were relying on these retries to wait for the metadata server to be up.

System.Management.ManagementClass biosClass = new ("Win32_BIOS");
using var instances = biosClass.GetInstances();

foreach(var instance in instances) using (instance)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need to dispose of every instance, should we do that regardless of whether we have an early "out"? Or are they only allocated lazily by the enumerator?
(Either way, I'd prefer to use more braces and indentation instead of this formatting, personally.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed braces and indetantion, and also, we are now iterating over the whole collection to dispose of all possible instances (unlikely there's more than one though).

foreach(var instance in instances) using (instance)
{
// We should only find one instance for Win32_BIOS class.
// This will throw a ManagementException "NotFound" if the "Manufacturer" property
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if there are multiple instances, it could be present in one other than the first one, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in principle I guess it could happen. We are now iterating over all instances.

// We should only find one instance for Win32_BIOS class.
// This will throw a ManagementException "NotFound" if the "Manufacturer" property
// is not present. That's fine, we are catching the exception elsewhere and logging it.
return instance["Manufacturer"]?.ToString() == "Google";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a somewhat different check to the Linux one - is that okay?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's different checks.

Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked about all of this - Amanda will make a few tweaks, but most of my comments were irrelevant :)

Copy link
Contributor Author

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jskeet I've added a third commit with the changes in case you want and can to take a look. Else since we had talked about these, I'll squash in a single commit and merge later today.

@@ -295,7 +296,11 @@ public static Task<bool> IsRunningOnComputeEngine()
return isRunningOnComputeEngineCached.Value;
}

private static async Task<bool> IsRunningOnComputeEngineNoCache()
private static async Task<bool> IsRunningOnComputeEngineNoCacheAsync() =>
await IsMetadataServerAvailableAsync().ConfigureAwait(false)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this. Keeping as is for the time being to cause the least disruption to users that were relying on these retries to wait for the metadata server to be up.

return false;
}

private async static Task<bool> IsGoogleBiosAsync()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
else
{
Logger.Info("GCE residency detection through BIOS checking is only supported in Windows and Linux platforms.");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, better with "on".

bool IsWindows()
{
#if NET45 || NET461
// RuntimeInformation.IsOsPlatform is not available for these targets.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was mistaken with this, RuntimeInformation.IsOsPlatform is supported in NET461. So that only leaves NET45, but that's going away in January because of #2561, so I'm changing this to always return false in NET45.

productName = await streamReader.ReadLineAsync().ConfigureAwait(false);
}
productName = productName?.Trim();
return productName == "Google" || productName == "Google Compute Engine";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked.

System.Management.ManagementClass biosClass = new ("Win32_BIOS");
using var instances = biosClass.GetInstances();

foreach(var instance in instances) using (instance)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed braces and indetantion, and also, we are now iterating over the whole collection to dispose of all possible instances (unlikely there's more than one though).

foreach(var instance in instances) using (instance)
{
// We should only find one instance for Win32_BIOS class.
// This will throw a ManagementException "NotFound" if the "Manufacturer" property
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in principle I guess it could happen. We are now iterating over all instances.

// We should only find one instance for Win32_BIOS class.
// This will throw a ManagementException "NotFound" if the "Manufacturer" property
// is not present. That's fine, we are catching the exception elsewhere and logging it.
return instance["Manufacturer"]?.ToString() == "Google";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's different checks.

@jskeet
Copy link
Collaborator

jskeet commented Oct 27, 2023

Yup, looks good.

@amanda-tarafa
Copy link
Contributor Author

Yup, looks good.

Thanks, merging and rebasing. I'll prepara a PR for a release on Monday as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve GCE detection by checking Google hardware
2 participants