public PluginExecutionResult Execute(PluginExecutionData executionData) { CtcSettings.Initialize(executionData); ConnectivityPrintActivityData activityData = executionData.GetMetadata <ConnectivityPrintActivityData>(CtcMetadataConverter.Converters); PrinterFamilies family = (PrinterFamilies)Enum.Parse(typeof(PrinterFamilies), Enum <ProductFamilies> .Value(activityData.ProductFamily)); Printer.Printer printer = PrinterFactory.Create(family, IPAddress.Parse(activityData.Ipv4Address)); if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv4Address), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer IPv4 Address is not accessible\n\n", "IPv4 address: {0}\n".FormatWith(activityData.Ipv4Address)), @"IPv4 Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer IPv4 Address is not accessible")); } // create instance of ews adapter EwsWrapper.Instance().Create(family, activityData.ProductName, activityData.Ipv4Address, Path.Combine(activityData.SitemapPath, activityData.SiteMapVersion), BrowserModel.Firefox); EwsWrapper.Instance().Start(); EwsWrapper.Instance().WakeUpPrinter(); EwsWrapper.Instance().SetAdvancedOptions(); EwsWrapper.Instance().EnableSnmpv1v2ReadWriteAccess(); //Enabling IPV6 startup EwsWrapper.Instance().SetDHCPv6OnStartup(true); EwsWrapper.Instance().SetIPv6(false); EwsWrapper.Instance().SetIPv6(true); // If printer is not available, assign default IPAddress if (printer.PingUntilTimeout(IPAddress.Parse(activityData.Ipv4Address), 1)) { // Get All Ipv6 Addresses activityData.Ipv6LinkLocalAddress = printer.IPv6LinkLocalAddress?.ToString() ?? string.Empty; activityData.Ipv6StateFullAddress = printer.IPv6StateFullAddress?.ToString() ?? string.Empty; activityData.Ipv6StatelessAddress = printer.IPv6StatelessAddresses.Count == 0 ? string.Empty : printer.IPv6StatelessAddresses[0].ToString(); } else { activityData.Ipv6LinkLocalAddress = string.Empty; activityData.Ipv6StateFullAddress = string.Empty; activityData.Ipv6StatelessAddress = string.Empty; } foreach (Ipv6AddressTypes addressType in activityData.Ipv6AddressTypes) { if (Ipv6AddressTypes.LinkLocal == addressType) { if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv6LinkLocalAddress), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer Link Local Address is not accessible\n\n", "Link local address: {0}\n".FormatWith(activityData.Ipv6LinkLocalAddress), "Check if Stateless and Stateful address are pinging if you have selected it.\n", "Stateless: {0}, Stateful: {1}".FormatWith(activityData.Ipv6StatelessAddress, activityData.Ipv6StateFullAddress)), @"Link Local Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer Link Local Address is not accessible")); } } else if (Ipv6AddressTypes.Stateless == addressType) { if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv6StatelessAddress), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer Stateless Address is not accessible\n\n", "Stateless address: {0}\n".FormatWith(activityData.Ipv6StatelessAddress), "Check if Stateful address is pinging if you have selected it.\n", "Stateful: {0}".FormatWith(activityData.Ipv6StateFullAddress)), @"Stateless Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer Stateless Address is not accessible")); } } else if (Ipv6AddressTypes.Stateful == addressType) { if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv6StateFullAddress), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer Stateful Address is not accessible\n\n", "Stateful address: {0}\n".FormatWith(activityData.Ipv6StateFullAddress)), @"Stateful Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer Stateful Address is not accessible")); } } } //Reservation for Primary Printer string value = activityData.Ipv4Address.Split(new char[] { '.' })[2]; string serverIp = DHCP_SERVER_IP_FORMAT.FormatWith(value); TraceFactory.Logger.Info("Server IP : {0}".FormatWith(serverIp)); //string serverIp = Printer.Printer.GetDHCPServerIP(IPAddress.Parse(activityData.Ipv4Address)).ToString(); string printerMacAddress = printer.MacAddress.Replace(":", string.Empty); using (DhcpApplicationServiceClient client = DhcpApplicationServiceClient.Create(serverIp)) { string scope = client.Channel.GetDhcpScopeIP(serverIp); TraceFactory.Logger.Info("Scope : {0}".FormatWith(scope)); client.Channel.DeleteReservation(serverIp, client.Channel.GetDhcpScopeIP(serverIp), activityData.Ipv4Address, printerMacAddress); if (client.Channel.CreateReservation(serverIp, client.Channel.GetDhcpScopeIP(serverIp), activityData.Ipv4Address, printerMacAddress, ReservationType.Both)) { TraceFactory.Logger.Info("Primary Printer IP Address Reservation in DHCP Server for both DHCP and BOOTP : Succeeded"); } else { TraceFactory.Logger.Info("Primary Printer IP Address Reservation in DHCP Server for both DHCP and BOOTP: Failed"); return(new PluginExecutionResult(PluginResult.Failed, "Primary Printer IP Address Reservation in DHCP Server for both DHCP and BOOTP: Failed")); } } EwsWrapper.Instance().SetAdvancedOptions(); string documentsPath = activityData.DocumentsPath; string documentsSharePath = Path.Combine(CtcSettings.ConnectivityShare, activityData.ProductFamily.ToString()); // Combine the connectivity share path with the selected document // In case of Re-run, path is already constructed. Hence do not construct it again. if (!Directory.Exists(documentsPath)) { if (!documentsPath.StartsWith(documentsSharePath, StringComparison.CurrentCulture)) { documentsPath = Path.Combine(documentsSharePath, activityData.DocumentsPath, ConnectivityPrintConfigurationControl.DIRECTORY_DOCUMENTS); activityData.DocumentsPath = documentsPath; } } if (activityData.IsWspTestsSelected) { printer.NotifyWSPrinter += printer_NotifyWSPAddition; if (printer.Install(IPAddress.Parse(activityData.Ipv4Address), Printer.Printer.PrintProtocol.WSP, activityData.DriverPackagePath, activityData.DriverModel)) { MessageBox.Show(@"WS Printer was added successfully.", @"WS Printer Successful", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show(@"WS Printer was not added successfully. All WS Print related tests will fail.", @"WS Printer Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } if (null == _printTests) { _printTests = new ConnectivityPrintTests(activityData); } foreach (int testNumber in activityData.SelectedTests) { ExecutionServices.SessionRuntime.AsInternal().WaitIfPaused(); _printTests.RunTest(executionData, testNumber, IPAddress.Parse(activityData.Ipv4Address), activityData.ProductFamily); } return(new PluginExecutionResult(PluginResult.Passed)); }
public PluginExecutionResult Execute(PluginExecutionData executionData) { CtcSettings.Initialize(executionData); ComplexPrintActivityData activityData = executionData.GetMetadata <ComplexPrintActivityData>(CtcMetadataConverter.Converters); /* Complex printing plugin might use more than 1 client machine based on user scenario. * All inputs related to printer are maintained in a configuration file in share location (etlhubrepo\boi\CTC\<Product_Family>) * Since multiple machines are trying to access the config file, file is copied to local machine. * */ // Get details from configuration file string configFilePath = Path.Combine(CtcSettings.ConnectivityShare, activityData.ProductFamily.ToString(), "CNP.xml"); TraceFactory.Logger.Debug("Config File path: {0}".FormatWith(configFilePath)); FileStream file = null; try { XmlDocument configFile = new XmlDocument(); string tempFilePath = Path.Combine(Path.GetTempPath(), "CNP.xml"); File.Copy(configFilePath, tempFilePath, true); file = new FileStream(tempFilePath, FileMode.Open, FileAccess.Read); configFile.Load(file); activityData.Ipv4Address = configFile.DocumentElement.SelectSingleNode("IPv4Address").InnerText; activityData.DriverPackagePath = configFile.DocumentElement.SelectSingleNode("DriverPath").InnerText; activityData.DriverModel = configFile.DocumentElement.SelectSingleNode("DriverModel").InnerText; activityData.ProductName = configFile.DocumentElement.SelectSingleNode("ProductName").InnerText; activityData.DocumentsPath = configFile.DocumentElement.SelectSingleNode("FilesPath").InnerText; activityData.SitemapsVersion = configFile.DocumentElement.SelectSingleNode("Sitemaps").InnerText; activityData.PrinterConnectivity = ConnectivityType.Wired; } catch (Exception exception) { TraceFactory.Logger.Fatal("Failed to read configuration from xml document. Exception details: {0}".FormatWith(exception.JoinAllErrorMessages())); } finally { if (null != file) { file.Close(); } } /* If a WS Print test is selected in user scenario, a pop-up needs to be shown to 'Add the printer'. * Read through all selected tests and keep track if WSP pop-up needs to be shown up. * */ // Check if WSP test is selected by checking the test attributes for each test bool isWSPSelected = false; foreach (int testNumber in activityData.SelectedTests) { // Fetch the TestDetailsAttribute of the test method matching the testNumber var attributes = typeof(ComplexPrintTests).GetMethods().Where(item => item.GetCustomAttributes(new TestDetailsAttribute().GetType(), false).Length > 0 && ((TestDetailsAttribute)item.GetCustomAttributes(new TestDetailsAttribute().GetType(), false)[0]).Id.Equals(testNumber)) .Select(x => x.GetCustomAttributes(new TestDetailsAttribute().GetType(), false)[0]); TestDetailsAttribute testAttributes = (TestDetailsAttribute)attributes.FirstOrDefault(); if (testAttributes.Category.Contains("WSP", StringComparison.CurrentCultureIgnoreCase)) { isWSPSelected = true; break; } } if (isWSPSelected) { TraceFactory.Logger.Debug("Please add WS Printer on client machine: {0}".FormatWith(Environment.MachineName)); } /* To keep track of whether a WSP test is added in any of the user scenario, a common file is maintained under shared location and all the clients need to update this file on WSP status. * Folder structure: etlhubrepo\boi\CTC\<Product_Family>temp\<Session_ID>.xml * Since many clients will be trying to write data to the xml file, check if xml is already created (by some other client), create if not. * If a WSP test is selected, an entry is made with 'Yes' as the value, else 'No' with machine hostname as the unique identifier for the node. * Status for the WS Print addition is maintained in 'Status' attribute. If scenario doesn't have a WSP test selected, 'Completed' status is added by default. Otherwise 'In Progress' is added. * * Locking mechanism: * Since its a shared file, a lock is applied when a file is in use by a machine. Lock file for writing the data and release once completed. * Acquire resource for max of 20 seconds to perform write operation. Wait for max of 3 minutes to use resource for writing into the file. (Waiting in Queue to write into the file) * */ string configFolder = Path.Combine(CtcSettings.ConnectivityShare, activityData.ProductFamily.ToString(), "temp"); // Check if folder exists already. if (!Directory.Exists(configFolder)) { Directory.CreateDirectory(configFolder); } string xmlFilePath = Path.Combine(configFolder, executionData.SessionId + ".xml"); XElement machines = null; // Check if file exists already. Create root node 'Machines' if file is not created else load the file if (!File.Exists(xmlFilePath)) { machines = new XElement("Machines"); } else { XDocument xmlDocument = XDocument.Load(xmlFilePath); machines = xmlDocument.Element("Machines"); } ReaderWriterLock fileLock = new ReaderWriterLock(); bool isFileWritten = false; DateTime currentTime = DateTime.Now; TimeSpan waitTime = TimeSpan.FromMinutes(3); Random randomTime = new Random(); do { // Since many clients are trying to access the file, generate a random timeout for acquiring lock on the file. int timeOut = randomTime.Next(10, 20); if (!fileLock.IsWriterLockHeld) { fileLock.AcquireWriterLock(TimeSpan.FromSeconds(timeOut)); XElement machine = new XElement("Machine", new XAttribute("VM_Name", Environment.MachineName), new XAttribute("WSP_Print", isWSPSelected ? "Yes" : "No"), new XAttribute("Status", isWSPSelected ? "In Progress" : "Completed")); machines.Add(machine); machines.Save(xmlFilePath); // Wait for sometime to release the lock after saving file. Thread.Sleep(TimeSpan.FromSeconds(10)); isFileWritten = true; fileLock.ReleaseWriterLock(); } } while (!isFileWritten && DateTime.Now.Subtract(waitTime) <= currentTime); /* Check if printer is accessible with IPv4 address and IPv6 addresses: Linklocal, Stateless and Stateful address. * Pop-up a message box if printer address is not pinging. * */ PrinterFamilies family = (PrinterFamilies)Enum.Parse(typeof(PrinterFamilies), Enum <ProductFamilies> .Value(activityData.ProductFamily)); Printer.Printer printer = PrinterFactory.Create(family, IPAddress.Parse(activityData.Ipv4Address)); // If printer is not available, assign default IPAddress if (printer.PingUntilTimeout(IPAddress.Parse(activityData.Ipv4Address), 1)) { // Get All Ipv6 Addresses activityData.Ipv6LinkLocalAddress = printer.IPv6LinkLocalAddress == null ? string.Empty : printer.IPv6LinkLocalAddress.ToString(); activityData.Ipv6StateFullAddress = printer.IPv6StateFullAddress == null ? string.Empty : printer.IPv6StateFullAddress.ToString(); activityData.Ipv6StatelessAddress = printer.IPv6StatelessAddresses.Count == 0 ? string.Empty : printer.IPv6StatelessAddresses[0].ToString(); } else { activityData.Ipv6LinkLocalAddress = string.Empty; activityData.Ipv6StateFullAddress = string.Empty; activityData.Ipv6StatelessAddress = string.Empty; } if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv4Address), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer IPv4 Address is not accessible\n\n", "IPv4 address: {0}\n".FormatWith(activityData.Ipv4Address)), "IPv4 Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer IPv4 Address is not accessible")); } if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv6LinkLocalAddress), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer Link Local Address is not accessible\n\n", "Link local address: {0}\n".FormatWith(activityData.Ipv6LinkLocalAddress), "Check if Stateless and Stateful address are pinging if you have selected it.\n", "Stateless: {0}, Stateful: {1}".FormatWith(activityData.Ipv6StatelessAddress, activityData.Ipv6StateFullAddress)), "Link Local Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer Link Local Address is not accessible")); } if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv6StatelessAddress), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer Stateless Address is not accessible\n\n", "Stateless address: {0}\n".FormatWith(activityData.Ipv6StatelessAddress), "Check if Stateful address is pinging if you have selected it.\n", "Stateful: {0}".FormatWith(activityData.Ipv6StateFullAddress)), "Stateless Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer Stateless Address is not accessible")); } if (!NetworkUtil.PingUntilTimeout(IPAddress.Parse(activityData.Ipv6StateFullAddress), TimeSpan.FromSeconds(10))) { MessageBox.Show(string.Concat("Printer Stateful Address is not accessible\n\n", "Stateful address: {0}\n".FormatWith(activityData.Ipv6StateFullAddress)), "Stateful Address Not Accessible", MessageBoxButtons.OK, MessageBoxIcon.Error); return(new PluginExecutionResult(PluginResult.Failed, "Printer Stateful Address is not accessible")); } /* Since multiple clients can access drivers, print driver is copied to local machine so as to avoid 'File in use' exception. * Driver path is updated to local temp directory for further use. * */ string tempDriverDirectory = Path.Combine(Path.GetTempPath(), "PrintDriver"); TraceFactory.Logger.Debug("Local printer driver location: {0}".FormatWith(tempDriverDirectory)); if (Directory.Exists(tempDriverDirectory)) { Directory.Delete(tempDriverDirectory, true); } foreach (string dirPath in Directory.GetDirectories(activityData.DriverPackagePath, "*", SearchOption.AllDirectories)) { Directory.CreateDirectory(dirPath.Replace(activityData.DriverPackagePath, tempDriverDirectory)); } foreach (string filePath in Directory.GetFiles(activityData.DriverPackagePath, "*.*", SearchOption.AllDirectories)) { File.Copy(filePath, filePath.Replace(activityData.DriverPackagePath, tempDriverDirectory), true); } activityData.DriverPackagePath = tempDriverDirectory; // By default, adding P9100 printer so that driver installation is complete while adding WS Printer. printer.Install(IPAddress.Parse(activityData.Ipv4Address), Printer.Printer.PrintProtocol.RAW, activityData.DriverPackagePath, activityData.DriverModel, 9100); // If WSP test is selected, Show a pop-up to Add the printer. if (isWSPSelected) { /* If a WSP test is selected in any scenario created by user, pop a message box to add the printer. * Status on whether a WSP test is selected are maintained in the config file (etlhubrepo\boi\CTC\<Product_Family>temp\<Session_ID>.xml) with attribute 'WSP_Print'. * In case this scenario is added with WSP test, Pop-up message. Once the Ok button is clicked, updated the 'Status' on config file to 'Completed'. * */ XElement localMachine = null; XDocument document = XDocument.Load(xmlFilePath); XElement element = document.Element("Machines"); foreach (var vm in element.Elements("Machine")) { if (vm.Attribute("VM_Name").Value.Equals(Environment.MachineName)) { localMachine = vm; TraceFactory.Logger.Info("Machine: {0}".FormatWith(localMachine.Attribute("VM_Name").Value)); break; } } MessageBox.Show("Add WS Printer and click 'OK'.", "Add WS Printer", MessageBoxButtons.OK, MessageBoxIcon.Information); localMachine.SetAttributeValue("Status", "Completed"); element.Save(xmlFilePath); } /* Wait till all clients are ready for execution: If a client is configured with WSP test, wait till user adds the printer. * This case is handled with updation of the config file on status of WS Printer installation. * Traverse through all Elements and check for 'Status' attribute to know the status on installation of WS Printer. * */ bool isWSPrinterInstalled = true; do { TraceFactory.Logger.Debug("Waiting for all clients to complete WS Printer installation."); // In case isWSPrinterInstalled is set to false while traversing through the config file, set it back to true for next iteration isWSPrinterInstalled = true; // Wait for some time so that other clients update the status on WS Printer installation Thread.Sleep(TimeSpan.FromSeconds(10)); // Reload the file to get the most updated data XDocument xDocument = XDocument.Load(xmlFilePath); XElement xElement = xDocument.Element("Machines"); foreach (var vm in xElement.Elements("Machine")) { isWSPrinterInstalled &= "Completed".Equals(vm.Attribute("Status").Value); } } while (!isWSPrinterInstalled); if (null == _printTests) { _printTests = new ComplexPrintTests(activityData); } foreach (int testNumber in activityData.SelectedTests) { ExecutionServices.SessionRuntime.AsInternal().WaitIfPaused(); _printTests.RunTest(executionData, testNumber, IPAddress.Parse(activityData.Ipv4Address), activityData.ProductFamily); } return(new PluginExecutionResult(PluginResult.Passed)); }