Ejemplo n.º 1
0
        /// <summary>
        /// Install patches
        /// </summary>
        public void InstallPatches()
        {
            string patchConfigFilePath = Path.Combine(Path.GetPathRoot(Assembly.GetExecutingAssembly().Location), "plugins", "patchplugin", PatchConfigurationFileName);

            PatchConfiguration patchConfiguration = new PatchConfiguration();

            patchConfiguration.Load(patchConfigFilePath);

            if (patchConfiguration.PatchMap == null || patchConfiguration.PatchMap.Count == 0)
            {
                LogUtils.WriteTrace(DateTime.UtcNow, "PatchUtil: no patches to install.");
                return;
            }

            // First check if all patches have been installed
            IList <PatchConfiguration.Patch> uninstalledPatches = GetUninstalledPatches(patchConfiguration);

            if (uninstalledPatches.Count == 0)
            {
                LogUtils.WriteTrace(DateTime.UtcNow, "PatchUtil: all patches have been installed.");
                return;
            }

            try
            {
                InstallPatches(uninstalledPatches, patchConfiguration.OverallTimeoutSeconds * 1000);

                // Wait timeout and return
                DateTime startTime = DateTime.UtcNow;
                while (DateTime.UtcNow < startTime + TimeSpan.FromSeconds(patchConfiguration.OverallTimeoutSeconds))
                {
                    uninstalledPatches = GetUninstalledPatches(patchConfiguration);
                    if (uninstalledPatches.Count == 0)
                    {
                        LogUtils.WriteTrace(DateTime.UtcNow, "PatchUtil: all patches have been installed. Exit and reboot without waiting until timeout.");
                        return;
                    }

                    LogUtils.WriteTrace(DateTime.UtcNow, "PatchUtil: sleep 1 minutes before checking patch installation again.");
                    Thread.Sleep(TimeSpan.FromMinutes(1));
                }
            }
            catch (Exception e)
            {
                // Log the exception
                LogUtils.WriteTrace(DateTime.UtcNow, "PatchUtil: Patch installation encountered an Exception: " + e);

                if (!_rebootRequired)
                {
                    // We haven't start install patches, so throw and the process will be restarted (without reboot)
                    throw;
                }

                // Eat the exception and the VM is going to be rebooted.
                LogUtils.WriteTrace(DateTime.UtcNow, "PatchUtil: At least one patch is installed, waiting to be rebooted.");
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Get uninstalled patches list
        /// </summary>
        /// <param name="patchConfiguration"></param>
        /// <returns></returns>
        private static IList <PatchConfiguration.Patch> GetUninstalledPatches(PatchConfiguration patchConfiguration)
        {
            List <PatchConfiguration.Patch> uninstalledPatches = new List <PatchConfiguration.Patch>();

            foreach (PatchConfiguration.Patch patch in patchConfiguration.PatchMap.Values)
            {
                LogUtils.WriteTrace(DateTime.UtcNow,
                                    string.Format("PatchUtil: check registry setting for patch '{0}'", patch.Name));

                if (patch.RegistrySettings == null)
                {
                    continue;
                }

                foreach (PatchConfiguration.PatchRegistry reg in patch.RegistrySettings)
                {
                    LogUtils.WriteTrace(DateTime.UtcNow, string.Format(@"PatchUtil: read registry value '{0}\{1}' for patch '{2}'",
                                                                       reg.RegistryKeyName, reg.RegistryValueName, patch.Name));

                    object value = Registry.GetValue(reg.RegistryKeyName, reg.RegistryValueName, null);

                    if (value == null)
                    {
                        LogUtils.WriteTrace(DateTime.UtcNow,
                                            string.Format(
                                                @"PatchUtil: registry value '{0}\{1}' does not exist or has null value. Need to install patch '{2}'",
                                                reg.RegistryKeyName, reg.RegistryValueName, patch.Name));

                        // PatchConfiguration doesn't allow the same patch be defined multiple times. No need to check it here again.
                        uninstalledPatches.Add(patch);

                        // Go to next patch
                        break;
                    }

                    // Compare registry value. We only support REG_DWORD and REG_SZ for now
                    Type valueType = value.GetType();

                    if (valueType == typeof(string))
                    {
                        string stringValue = value as string;

                        LogUtils.WriteTrace(DateTime.UtcNow,
                                            string.Format(
                                                @"PatchUtil: registry value '{0}\{1}' has string value: '{2}'",
                                                reg.RegistryKeyName, reg.RegistryValueName, stringValue));

                        // If reg.ExpectedValue is null, we only validate there is a reg value there.
                        if (reg.ExpectedValue == null)
                        {
                            LogUtils.WriteTrace(DateTime.UtcNow, @"PatchUtil: skip validation because the ExpectedValue is null");
                        }
                        else if (!string.Equals(stringValue, reg.ExpectedValue, StringComparison.OrdinalIgnoreCase))
                        {
                            LogUtils.WriteTrace(DateTime.UtcNow, string.Format(
                                                    @"PatchUtil: registry value '{0}\{1}' does not match the expected value: '{2}'. Need to install patch '{3}'",
                                                    reg.RegistryKeyName,
                                                    reg.RegistryValueName,
                                                    reg.ExpectedValue,
                                                    patch.Name));

                            // Add to the list
                            uninstalledPatches.Add(patch);

                            // Go to next patch
                            break;
                        }
                    }
                    else if (valueType == typeof(int))
                    {
                        int intValue = (int)value;

                        LogUtils.WriteTrace(DateTime.UtcNow, string.Format(@"PatchUtil: registry value '{0}\{1}' has integer value: '{2}'",
                                                                           reg.RegistryKeyName, reg.RegistryValueName, intValue));

                        int expectedValue;
                        if (reg.ExpectedValue == null)
                        {
                            LogUtils.WriteTrace(DateTime.UtcNow, @"PatchUtil: skip validation because the ExpectedValue is null");
                        }
                        else if ((!int.TryParse(reg.ExpectedValue, out expectedValue)) || (expectedValue != intValue))
                        {
                            LogUtils.WriteTrace(DateTime.UtcNow, string.Format(
                                                    @"PatchUtil: registry value '{0}\{1}' does not match the expected value: '{2}'. Need to install patch '{3}'",
                                                    reg.RegistryKeyName,
                                                    reg.RegistryValueName,
                                                    reg.ExpectedValue,
                                                    patch.Name));

                            // Add to the list
                            uninstalledPatches.Add(patch);

                            // Go to next patch
                            break;
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "PatchUtil: Registry value type '{0}' is not supported.", valueType));
                    }
                }
            }

            return(uninstalledPatches);
        }