I have been attempting to start an instance of EC2 in C# without luck.
When passing in an instance id to start the instance I get an error that the instance cannot be found despite that I am passing in an instance ID that I have obtained from the object property.
Amazon made huge efforts to integrate its AWS Cloud .Net SDK To VS2008 & VS 2010
1 - Download and Install the AWS SDK msi
2 - Create an AWS Console project, enter your credentials (available from your AWS Console under your login name menu on the top right corner)
3 - Add the following code (see below images).
4 - Your're done. It's very straightforward. You can check the programmatic start/stop success by refreshing your AWS Console Screen.
AmazonEC2 ec2 = AWSClientFactory.CreateAmazonEC2Client();
//Start Your Instance
ec2.StartInstances(new StartInstancesRequest().WithInstanceId("i-00000000"));
//Stop it
ec2.StopInstances(new StopInstancesRequest().WithInstanceId("i-00000000"));
You just need to replace "i-00000000" by your instance Id (available in your AWS Management Console)
Hope this helps those googling this and stumbling upon this question (as I did myself) start off quickly. Following these simple steps via these wizards will spare you considerable headaches.
Try something like this with the AWSSDK to start new instances of an "image id":
RunInstancesResponse response = Client.RunInstances(new RunInstancesRequest()
.WithImageId(ami_id)
.WithInstanceType(instance_type)
.WithKeyName(YOUR_KEYPAIR_NAME)
.WithMinCount(1)
.WithMaxCount(max_number_of_instances)
.WithUserData(Convert.ToBase64String(Encoding.UTF8.GetBytes(bootScript.Replace("\r", ""))))
);
(Note: The .WithUserData() is optional and is used above to pass a short shell script.)
If the call is successful the response should contain a list of instances. You can use something like this to create a list of "instance ids":
if (response.IsSetRunInstancesResult() && response.RunInstancesResult.IsSetReservation() && response.RunInstancesResult.Reservation.IsSetRunningInstance())
{
List<string> instance_ids = new List<string>();
foreach (RunningInstance ri in response.RunInstancesResult.Reservation.RunningInstance)
{
instance_ids.Add(ri.InstanceId);
}
// do something with instance_ids
...
}
Be mindful that Amazon AWS instances exist only in one region. If your instance id i-12345 is in the EU-West-1 region, and you just make a new EC2Client and tell the client to start i-12345 it may well complain that it cannot find that instance, because the client started up in the us-east-1 region, which does not have i-12345 instance.
Your call that creates the client should specify the region, if it is not the default region (I've no idea which AWS region is default, so I specify every time):
AmazonEC2 ec2 = AWSClientFactory.CreateAmazonEC2Client(
new Amazon.EC2.AmazonEC2Config().WithServiceURL("https://eu-west-1.ec2.amazonaws.com")
);
Ok, this is the FULL, end-to-end instructions.
1. Install AWSSDK.Core and AWSSDK.EC2 using Nuget Package Manager.
2. Then copy this whole class to your project. AccessKey and Secret are obtained in AWS IAM. You will need to ensure the user you create has "AmazonEC2FullAccess" (You can probably use a lower-level permission policy, I am just lazy here :D). region is your AW S EC2 instance region. and Instance ID can be found in the EC2 dashboard list. Simple, works perfectly... You can also write extra code to manage the response object.
3. Be mindful if you are behind a proxy, you will have to configure it (I havent included code here).
public class AWSClass : IDisposable
{
Amazon.EC2.AmazonEC2Client _client;
public AWSClass(string region, string AccessKey, string Secret)
{
RegionEndpoint EndPoint = RegionEndpoint.GetBySystemName(region);
Amazon.Runtime.BasicAWSCredentials Credentials = new Amazon.Runtime.BasicAWSCredentials(AccessKey, Secret);
_client = new AmazonEC2Client(Credentials, EndPoint);
}
public void Dispose()
{
_client = null;
}
public void StopInstance(string InstanceID)
{
StopInstancesResponse response = _client.StopInstances(new StopInstancesRequest
{
InstanceIds = new List<string> {InstanceID }
});
//Can also do something with the response object too
}
public void StartInstance(string InstanceID)
{
StartInstancesResponse response = _client.StartInstances(new StartInstancesRequest
{
InstanceIds = new List<string> { InstanceID }
});
}
}
try this.
var startRequest = new StartInstancesRequest
{
InstanceIds = new List<string>() { instanceId }
};
bool isError = true;
StartInstancesResponse startInstancesResponse = null;
while (isError)
{
try
{
startInstancesResponse=amazonEc2client.StartInstances(startRequest);
isError = false;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
isError = true;
}
}
Related
I've a C# client witch i want to monitor with azure insights.
I've added the following Nugets:
Microsoft.ApplicationInsights v2.9.1
Microsoft.ApplicationInsights.Agent.Intercept v2.4.0
Microsoft.ApplicationInsights.DependencyCollector v2.9.1
Microsoft.ApplicationInsights.PerfCounterCollector v2.9.1
Microsoft.ApplicationInsights.Web v2.9.1
Microsoft.ApplicationInsights.WindowsServer v2.9.1
Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel v2.9.1
Microsoft.AspNet.TelemetryCorrelation v1.0.5
System.Diagnostics.DiagnosticSource v4.5.1
The problem is that the Azure Portal is recognizing my events and exceptions in the usage category but not as live metric stream. My Client is connected and the live metric stream is available but no temeletry data like tracked events or exceptions are shown. Even in Visual Studio there is no available Application Insights data during the debugging time.
I've tried a lot of times to uninstall and reinstall all the nugets. Updated them to the newest version but without any effort.
This is the related code for my Azure Client. The Payload is just a class with a few properties witch i want to track. It's mapped into a dictionary for the payload to send.
public override void Initialize()
{
try
{
base.Initialize();
var configuration = new TelemetryConfiguration();
configuration.InstrumentationKey = Configuration.AnalyticsCodeId;
var dependencies = new DependencyTrackingTelemetryModule();
dependencies.Initialize(configuration);
configuration.TelemetryInitializers.Add(new Microsoft.ApplicationInsights.Extensibility.OperationCorrelationTelemetryInitializer());
configuration.TelemetryInitializers.Add(new ClientIpHeaderTelemetryInitializer());
configuration.TelemetryInitializers.Add(new AccountIdTelemetryInitializer());
customTelemetry = new AzureCustomTelemetryInitializer(Payload);
configuration.TelemetryInitializers.Add(customTelemetry);
client = new TelemetryClient(configuration);
if (CheckTrackingIsAllowed())
InitLiveMetric(configuration);
}
catch (Exception e)
{
Log.Write(e);
}
}
private void InitLiveMetric(TelemetryConfiguration configuration)
{
QuickPulseTelemetryProcessor processor = null;
configuration.TelemetryProcessorChainBuilder
.Use((next) =>
{
processor = new QuickPulseTelemetryProcessor(next);
return processor;
})
.Build();
var quickPulse = new QuickPulseTelemetryModule();
quickPulse.Initialize(configuration);
quickPulse.RegisterTelemetryProcessor(processor);
}
public override void SendEventAsync(string eventName, string modulName)
{
if (!CheckTrackingIsAllowed())
return;
Task.Run(() =>
{
var p = MapAzurePayload(Payload);
client.TrackEvent(eventName, p);
});
}
This code seems to work properly as i can see the the tracked events and exceptions in the usage category in the Azure Portal. But as i said, not as live metric what would be very nice and must normally work with the code i think.
Any ideas why the live metric stream is not working as intended?
Edit: Found the reason... The problem is that my first track event is send when the client seems not to be ready at all. If I delayed the sending it works as intended.
My solution is to delay the first sending of a track. Not nice but i have no other idea...
I'm currently using in my project TuesPechkin version 2.1.1, and also TuesPechkin.Wkhtmltox.AnyCPU v0.12.4.1
This is some of my code:
byte[] result = null;
try
{
var globalSettings = CreateGlobalSettings(portraitMode);
var objectSettings = CreateObjectSettings(websiteUrl, urlParameters);
var document = new HtmlToPdfDocument
{
GlobalSettings = globalSettings
};
document.Objects.Add(objectSettings);
CreateEventLog.CreateInformationLog("Ready to convert PDF");
result = Converter.Convert(document);
CreateEventLog.CreateInformationLog(result == null
? "Conversion failed using the Pechkin library"
: "PDF conversion finished");
I run this code in 3 different environments:
On my local machine it runs fine and it generates the file in 3 seconds.
On one of my servers (let's call it Server A) it runs fine and it generates the file in 3 seconds.
On the other of my servers (let's call it Server B) it holds for 1min (for some reason I don't understand) during the Converter.Convert part, and after that minute it returns null.
Server A and Server B have the same setup (CPU, RAM, etc)
There's no peak increase on Server B during conversion.
Any suggestions/ideas?
I found what the issue is.
The URL I'm trying to convert is in a Presentation Layer, which is deployed in a separate server. Pechkin converter is in a Business Layer.
In Server A, I can access the URL from the Business Server.
In Server B, I cannot access the URL from the Business Server.
This is probably some firewall exception that needs to be created.
It would be nice though to have TuesPechkin, returning an error saying it cannot access the URL.
It is important to check how you get the convert, dispose issue may cause problem
Just check code form here
public static IConverter GetConverter()
{
lock (Locker)
{
if (converter != null)
{
return converter;
}
var tempFolderDeployment = new TempFolderDeployment();
var winAnyCpuEmbeddedDeployment = new WinAnyCPUEmbeddedDeployment(tempFolderDeployment);
IToolset toolSet;
if (HostingEnvironment.IsHosted)
{
toolSet = new RemotingToolset<PdfToolset>(winAnyCpuEmbeddedDeployment);
}
else
{
toolSet = new PdfToolset(winAnyCpuEmbeddedDeployment);
}
converter = new ThreadSafeConverter(toolSet);
}
return converter;
}
I am working on an application which is deployed to a TEST and then a LIVE webserver.
I want the class library I am working on to use the correct service endpoint when it is deployed.
Currently the code is as follows;
var data = new SettingsViewModel()
{
ServiceURI = Constants.LIVE_ENDPOINT_SERVICE_ADDRESS,
AutoSync = Constants.DEFAULT_AUTO_SYNC,
AppDataFolder = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ROOT_FOLDER, Constants.DATA_FOLDER),
MapKey = Constants.BASIC_MAP_KEY,
Logging = false
};
#if DEBUG
data.ServiceURI = Constants.DEV_ENDPOINT_SERVICE_ADDRESS;
#endif
As you can see, this can only pick up the DEV or the LIVE endpoints. This code cannot distinguish whether the webserver is LIVE or TEST
I thought about setting up an App.Config file and get the correct Endpoint from there. But when I create a new item, the Config template is not listed. So how do I do this?
For now I could propose this solution :
public static class Constants
{
public static string GetEndPoint()
{
// Debugging purpose
if (System.Diagnose.Debug.IsAttached)
{
return DEV_ENDPOINT_SERVICE_ADDRESS;
}
else if ( Environment.MachineName == "Test Server" ) // You need to know your test server machine name at hand.
{
return "Return test Server endpoint"
}
else
{
return "Return live server endpoint";
}
}
}
You can used it in your SettingsViewModel like this:
var data = new SettingsViewModel()
{
ServiceURI = Constants.GetEndPoint(),
AutoSync = Constants.DEFAULT_AUTO_SYNC,
AppDataFolder = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ROOT_FOLDER, Constants.DATA_FOLDER),
MapKey = Constants.BASIC_MAP_KEY,
Logging = false
};
The drawback for this solution is, if you change your test server you need to change is manually in your code.
Having done some research I realise I need to clarify something. The application I am working on is a Windows RT application and this does not allow config files. The solution I am meant to use is to use local settings, but these do not reference an external file like an App.Config. If I want to change the location of an EndPoint then I am going to have to specify where that is in the code.
I've written a custom action for an installer project that does the following:
Checks existing websites to see if any exist with the same name put
in by the user.
Creates the website in IIS if it doesn't exist.
Creates an application pool.
Assigns the application pool to the created website.
When it comes to assigning the application pool I get and error:
The configuration object is read only, because it has been committed
by a call to ServerManager.CommitChanges(). If write access is
required, use ServerManager to get a new reference.
This baffles me as it seems to suggest that I can't assign the newly created application pool with the ServerManager.CommitChanges() call. However, everything else works fine using this, which I wouldn't expect if this was an issue.
Here is my code:
I have a ServerManager instance created like so:
private ServerManager mgr = new ServerManager();
In my Install method I do the following:
Site site = CreateWebsite();
if (site != null)
{
CreateApplicationPool();
AssignAppPool(site);
}
Check existing websites - done in OnBeforeInstall method
private Site CheckWebsites()
{
SiteCollection sites = null;
Site site = null;
try
{
sites = mgr.Sites;
foreach (Site s in sites)
{
if (!string.IsNullOrEmpty(s.Name))
{
if (string.Compare(s.Name, targetSite, true) == 0) site = s;
}
}
}
catch{}
return site;
}
CreateWebSite method:
private Site CreateWebsite()
{
Site site = CheckWebsites();
if (site == null)
{
SiteCollection sites = mgr.Sites;
int port;
Int32.TryParse(targetPort, out port);
site = sites.Add(targetSite, targetDirectory, port);
mgr.CommitChanges();
}
else
{
//TO DO - if website already exists edit settings
}
return site;
}
Create App Pool
//non-relevant code...
ApplicationPool NewPool = mgr.ApplicationPools.Add(ApplicationPool);
NewPool.AutoStart = true;
NewPool.ManagedRuntimeVersion = "4.0";
NewPool.ManagedPipelineMode = ManagedPipelineMode.Classic;
mgr.CommitChanges();
Assign App Pool
private void AssignAppPool(Site site)
{
site.ApplicationDefaults.ApplicationPoolName = ApplicationPool; //ERRORS HERE
mgr.CommitChanges();
}
I can't see why a site could be created, an app pool created but then not assigned. Help.
I finally realised that the 'configuration object' referred to in the error was the 'site'. Seems obvious now, but basically I needed to re-get the site to then assign the app pool to it. I think this is allow the previous changes to take place and then pick them up. So I altered my code by removing the need to pass the Site into private void AssignAppPool() and just getting the site again like this:
Site site = mgr.Sites["TestWebApp"];
I just deleted a task using the Rally website, but when a search for task using the REST API it doesn't return it. I assumed that it should return with the flag "Recycled".
Can anybody help me?
Regards,
Paulo
This is an inconsistency in the WSAPI. Unfortunately all queries are implicitly scoped (Recycled = false) so nothing that has been deleted will ever be returned from the artifact endpoints. There is also no way to access the contents of the recycle bin through the WSAPI.
I would encourage you to vote for the idea for this functionality at https://ideas.rallydev.com/ideas/D2374.
Although it's not ideal, you can get to the Recycle Bin through this REST endpoint:
https://rally1.rallydev.com/slm/webservice/1.40/recyclebin.js?workspace=/workspace/12345678910&project=/project/12345678911
Where the long integers the Workspace and Project OID's of interest.
Recycle bin entries look like the following:
{
_rallyAPIMajor: "1",
_rallyAPIMinor: "40",
_ref: "https://rally1.rallydev.com/slm/webservice/1.40/recyclebinentry/12345678910.js",
_refObjectName: "Test Case 3: Load in, run Analysis on Integer Grids",
_type: "RecycleBinEntry"
}
Where the Recycle Bin OID is unique and different from the OID of the Artifact that was deleted, so there's not a good way to map the Recycle Bin Entry to the Artifact that was deleted to create it. The Object Name could work, although you run the risk of duplicates. The Recycle Bin Entries also come with the same limitations as does the Recycle Bin in the UI - child objects are not shown/accessible.
If you want to walk the Recycle Bin from .NET, here's a quick example:
namespace RestExample_QueryRecycleBin {
class Program
{
static void Main(string[] args)
{
//Initialize the REST API
RallyRestApi restApi;
String userName = "user#company.com";
String userPassword = "topsecret";
// Set Rally parameters
String rallyURL = "https://rally1.rallydev.com";
String rallyWSAPIVersion = "1.40";
//Initialize the REST API
restApi = new RallyRestApi(userName,
userPassword,
rallyURL,
rallyWSAPIVersion);
// Specify workspace and project
string myWorkspace = "/workspace/12345678910";
string myProject = "/project/12345678911";
//Query for items
Request request = new Request("recyclebinentry");
request.Workspace = myWorkspace;
request.Project = myProject;
QueryResult queryResult = restApi.Query(request);
foreach (var result in queryResult.Results)
{
//Process item
string itemName = result["_refObjectName"];
string itemRef = result["_ref"];
Console.WriteLine(itemRef + ", " + itemName);
}
Console.ReadKey();
}
}
}