Get network usage from vmware.vim.vimclient - vmware

I'm using the underlying PowerCLI dll's to get some C# functionality and I just can't seem to find the documentation on how to get stat information.
Here's the PowerCLI that I'm trying to recreate in C#.
$vm | Get-Stat -stat 'net.usage.average'
I'm able to log in via VMware.Vim.VimClientImpl#connect method and I'm able to get a VM via the VMware.Vim.VimClient#FindEntityViews method, but from there I have no idea how to pull the network usage information and I haven't been able to find documentation on it via google either.
If there's documentation for these API's I would love to have them, but in the meantime, does anyone know how to pull this information?

I figured out the answer by staring at the SOAP requests and making a few intuitive leaps.
It's my belief that the VMWare API is state based similar to the way the X11 API is state based (you have handles to various objects that sit in memory on the server).
To be specific, you first connect a session to the server and then log in using that session. When you connect to a session vmware returns a list of 'manager objects' and their subsequent MoRef's. So the correct way to query this information is the following:
VimClient vimClient = new VMware.Vim.VimClientImpl();
var serviceContent = vimClient.Connect(hostname, VMware.Vim.CommunicationProtocol.Https, null);
var userSession = vimClient.Login(un, pwd);
NameValueCollection filter = new NameValueCollection();
filter.Add("Name", vmName2LookFor);
String[] viewProperties = null;
var VMs = vimClient.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, filter, viewProperties);
.Cast<VMware.Vim.VirtualMachine>()
.ToList();
var vm = VMs.FirstOrDefault(); // blindly grab for example purposes
var pm = new VMware.Vim.PerformanceManager(vimClient, serviceContent.PerfManager);
pm.QueryAvailablePerfMetric(vm.MoRef, DateTime.Now.AddDays(-1), DateTime.Now, null)
Note that when creating the PerformanceManager object we hand it the MoRef from the ServiceContent object that was created when originally connecting to the VMWare API.
I believe it's done this way to enable versioning the internal managers, but that specific point is a guess.
Also note that I used vimClient.FindEntityViews for illustrative purposes, there's also a singular vimClient.FindEntityView I could have used.
third note: MoRef stands for "Managed Object Reference".
fourth note: viewProperties in the vimClient.FindEntityViews tells vmware to only send the properties specified, for performance reasons. For example, finding a VM by IP involves grabbing all VM's and doing a search through them all for the VM with the IP you're looking for. You don't care about any other properties, so you tell vmware not to send the other properties. If you have a lot of infrastructure this is a very large speedup in performance. In the above case where I'm interested in the IP address, I would do
String[] viewProperties = new[]{ "Guest.Net" };

Related

How to receive public and private IPs while creating an instance in GCP using java sdks?

Whenever I create a virtual machine in AZURE and AWS with java SDK, the return object always give me public and private IPs.
Now I am exploring GCP java SDK and have successfully created an instance using it but how will I get ip addresses in return?
Instance instance = new Instance()
.setName(createInstance.getInstanceName())
.setMachineType(createInstance.getMachineTypeUrl()) //can provide 'prepare url' option
.setDisks(attachedDiskList)
.setNetworkInterfaces(networkInterfaceList)
.setCpuPlatform(createInstance.getCpuPlatform());
Operation instanceCreated = gcpCredentialService.getGcpClient()
.instances()
.insert(GcpContext.getContext().getServiceAccountProjectId(), completeRegion, instance)
.execute();
This object instanceCreated does not return public and private IPS in return.
I am new to GCP and struggling in this part.
Google's API (!) documentation is excellent and I encourage you to become familiar with navigating it as it will prove very helpful. While each SDK (library) is documented too, the underlying REST API methods and types are definitive and it should be straightforward to work upwards into your preferred language(s).
Compute Engine's [instances.insert] returns an Operation because the method is asynchronous. You'll need to query the Operation's state for successful completion of the operation (i.e. instance created) and then you can query the instance (instances.get, the response to which contains the properties that you need.
The documentation contains:
a (trivial but realistic) example code for the method.
guidance for using Operations.
required permissions for this task

Reset a Managed Chrome Device with SDK using Google Apps Script

I'm attempting to create a dashboard for admins to allow them to reset a chrome device managed by GoogleAdmin using google apps script.
I don't see any way to perform a reset using Admin SDK API. Can this be done?
If you want to deprovision and/or disable a ChromeOS device
The supported actions when using the Directory API, according to the documentation here are:
deprovision: Remove a device from management that is no longer active, being resold, or is being submitted for return / repair, use the deprovision action to dissociate it from management.
disable: If you believe a device in your organization has been lost or stolen, you can disable the device so that no one else can use it. When a device is disabled, all the user can see when turning on the Chrome device is a screen telling them that it’s been disabled, and your desired contact information of where to return the device.
Taking this into account, this is how the request would look like:
POST https://admin.googleapis.com/admin/directory/v1/customer/{customerId}/devices/chromeos/{resourceId}/action
If you want to reboot and/or remote powerwash a ChromeOS device
However, if you simply plan on doing a powerwash or a reboot, you can make use of the below information:
REBOOT: Reboot the device. Can only be issued to Kiosk and managed guest session devices.
REMOTE_POWERWASH: Wipes the device by performing a power wash. Executing this command in the device will remove all data including user policies, device policies and enrollment policies.
Warning: This will revert the device back to a factory state with no enrollment unless the device is subject to forced or auto enrollment. Use with caution, as this is an irreversible action!
Taking this into account, this is how the request would look like:
POST https://admin.googleapis.com/admin/directory/v1/customer/{customerId}/devices/chromeos/{deviceId}:issueCommand
Apps Script
As for applying any of these in Apps Script, you will have to add the Admin SDK API advanced service and choose the directory _v1 version and simulate any of the above requests.
Code
Assuming you want to remote powerwash a device, you will have to write something similar to this:
let resource = {
YOUR_RESOURCE_HERE;
"commandType": "REMOTE_POWERWASH"
};
let customerId = 'CUSTOMER_ID';
let deviceId = 'DEVICE_ID';
AdminDirectory.Customer.Devices.Chromeos.issueCommand(resource, customerId, deviceId);
Not what you are looking for?
You can simply create a feature request on Google's Issue Tracker and provide the details with regards to your task by filling in the form here.
Reference
Directory API Manage ChromeOS Devices.

aws get time according to cloud

I'm not seeing any answers for this when googling, so it's likely I'm asking a silly question, but here goes!
I want to call the aws api to get what time my cloud services think it is, because that appears to be different to my local server time (by a small but significant amount).
For a bit more context, I am running an automated test which needs to check that a new object is created in S3 as a result of the system under test working. The object which is created is given a timestamp in its name by AWS, based on the amazon server time. I use this timestamp to to distinguish the object from all the other objects in the bucket as it will be the only one with a time after the start of my test run. Unfortunately the time it gets given by amazon ends up being a few seconds before the test run started, because my server time is ahead of amazon's.
So if I could get the 'cloud' start time at the start of my test and compare that I won't have this problem.
EDIT
In case anyone has the same problem, I used this quick and dirty workaround in c#, in the spirit of the accepted answer but not quite as rigourous.
public async Task<DateTime> EstimateInternetTime()
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync("http://google.com");
return response.Headers.Date.Value.UtcDateTime;
}
There isn't a "cloud time", thus no way to ensure your timestamps match exactly to those used in AWS.
The best you can do is synchronize your clock using NTP to a public NTP server.
Amazon does have their own pool of NTP servers which you can use:
0.amazon.pool.ntp.org
1.amazon.pool.ntp.org
3.amazon.pool.ntp.org
2.amazon.pool.ntp.org
In many cases, EC2 instances are already configured to use these servers.
See the AWS documentation about configuring NTP on your Linux servers:
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-time.html#configure_ntp

strongloop/loopback - Change connection string based on route value

My application's users are geographically dispersed and data is stored in various regions. Each region has it's own data center and database server.
I would like to include a route value to indicate the region that the user wants to access and connect to, as follows:
/api/region/1/locations/
/api/region/2/locations/
/api/region/3/locations/
Depending on the region passed in, I would like to change the connection string being used. I assume this can be performed somewhere in the middleware chain, but don't know where/how. Any help is appreciated!
What should not be done
Loopback provides a method MyModel.attachTo (doesnt seem to be documented, but a reference to it is made there ).
But since it is a static method, it affects the entire Model, not a single instance.
So for this to work on a per-request basis, you must switch the DB right before the call to the datasource method, to make sure nothing async starts in between. I don't think this is possible.
This is an example using an operation hook (and define all datasources, include dbRegion1 below in datasources.json)
Bad, don't that below. Just for reference
Region.observe('loaded', function filterProperties(ctx, next) {
app.models.Region.attachTo(app.dataSources.dbRegion1);
}
But then you will most likely face concurrency issues when your API receives multiple requests in a short time.
(Another way to see it is that the server is no longer truly stateless, execution will not depend only on inputs but also on a shared state).
The hook may set region2 for request 2 while the method called after the hook was expecting to use region1 for request 1. This will be the case if something async is triggered between the hook and the actual call to the datasource method.
So ultimately, I don't think you should do that. I'm just putting it there because some people have recommended it in other SO posts, but it's just bad.
Potential option 1
Build an external re-routing server, that will re-route the requests from the API server to the appropriate region database.
Use the loopback-connector-rest in your API server to consume this microservice, and use it as a single datasource for all your models. This provides abstraction over database selection.
Then of course there is still the matter of implementing the microservice, but maybe you can find some other ORM than loopback's that will support database sharding, and use it in that microservice.
Potential option 2
Create a custom loopback connector that will act as router for MySQL queries. Depending on region value passed inside the query, re-route the query to the appropriate DB.
Option 3
Use a more distributed architecture.
Write a region-specific server to persist region-specific data.
Run for instance 3 different servers, each one configured for a region.
+ 1 common server for routing
Then build a routing middleware for your single user-facing REST api server.
Basic example:
var express = require('express');
var request = require('request');
var ips = ['127.0.0.1', '127.0.0.2'];
app.all('/api/region/:id', function (req, res, next) {
console.log('Reroute to region server ' + req.params.id);
request(ips[req.params.id], function (error, response, body) {
if (err) return next(err);
next(null, body);
});
});
Maybe this option is the easiest to do

Exchange Web Services, try to use ExchangeImpersonationType

I am trying to use EWS, first time trying to use the ExchangeServiceBinding. The code I am using is below:
_service = new ExchangeServiceBinding();
//_service.Credentials = new NetworkCredential(userName, userPassword, this.Domain);
_service.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
_service.Url = this.ServiceURL;
ExchangeImpersonationType ei = new ExchangeImpersonationType();
ConnectingSIDType sid = new ConnectingSIDType();
sid.PrimarySmtpAddress = this.ExchangeAccount;
ei.ConnectingSID = sid;
_service.ExchangeImpersonation = ei;
The application is an aspnet 3.5 trying to create a task using EWS. I have tried to use impersonation because I will not know the logon user's domain password, so I thought impersonation would be the best fit. Any thoughts on how I can utilize impersonation? Am I setting this correctly, I get an error while trying to run my application. I also tried without impersonation just to try to see if I can create a task, no luck either. Any help would be appreciated. Thanks.
Without broader context of your code snip, I can't tell for sure what's wrong, but here are a few things you might find useful...
You mention you had trouble connecting without impersonation.
I'm assuming you are using Exchange Server 2007 SP1, yes?
Do you have a mailbox for which you do know the username and password? If so, consider trying to connect to that mailbox, just to see if you can send an email or query for inbox count. That will help verify your connection at least.
As to exchange impersonation,
have the permissions been set on the Client Access Server (CAS) to enable impersonation?
Have the permissions been set on either the mailbox or mailbox database (containing the mailbox you are attempting to access)?
are you in a cross-forest scenario that requires additional trust relationships?
If not, that might explain why you cannot connect.
Some links you might find useful
Configuring (http://msdn.microsoft.com/en-us/library/bb204095.aspx)
Using Exchange impersonation (http://msdn.microsoft.com/en-us/library/bb204088.aspx)
Access multiple resource mailboxes (http://msexchangeteam.com/archive/2007/12/13/447731.aspx)