For a specific VM, I want to be able to retrieve the public IP address.
I know how to get all public IP addresses for a resource group, I also know how to get a nic-id for a specific VM - but I can't figure out how to connect the two.
This is what I have:
var resourceGroupName = "My-Resource-Group";
var vmName = "MyVM";
var subscriptionId = "bzz-bzz-bzz-bzz-bzz-bzz";
var tenantId = "bar-bar-bar-bar-bar-bar";
string clientId = "foo-foo-foo-foo-foo-foo";
string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var token = GetAccessTokenAsync(tenantId, clientId, clientSecret);
var credential = new TokenCredentials(token.Result.AccessToken);
var computeManagementClient = new ComputeManagementClient(credential) { SubscriptionId = subscriptionId };
var vmResult = await computeManagementClient.VirtualMachines.GetAsync(resourceGroupName, vmName, InstanceViewTypes.InstanceView);
//Get the NIC ID for the VM:
foreach (NetworkInterfaceReference nic in vmResult.NetworkProfile.NetworkInterfaces)
{
Console.WriteLine(" networkInterface id: " + nic.Id);
}
this gives me something like this:
/subscriptions/[guid]/resourceGroups/My-Resource-Group/providers/Microsoft.Network/networkInterfaces/myvm123
To get all public IPs for the resource group, I can do this:
using (var client = new NetworkManagementClient(credential))
{
client.SubscriptionId = subscriptionId;
foreach (var publicIpAddress in client.PublicIPAddresses.ListAll())
{
Console.WriteLine(publicIpAddress.IpAddress);
}
}
...But inspecting the properties of the nic-id and the public ip object, there are no obvious ways to get from one to the other.
Question:
How do I get from the nic-id string, to the actual public IP address for that VM/nic?
Helper function:
private static async Task<AuthenticationResult> GetAccessTokenAsync(string tenantId, string clientId, string clientSecret)
{
var cc = new ClientCredential(clientId, clientSecret);
var context = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var token = context.AcquireToken("https://management.azure.com/", cc);
if (token == null)
{
throw new InvalidOperationException("Could not get the token");
}
return token;
}
I found a workaround. Not pretty, but it works.
It assumes you already have a Microsoft.Azure.Management.Compute.Models.VirtualMachine object from something like this:
VirtualMachine vmResult = await computeManagementClient.VirtualMachines.GetAsync(resourceGroupName, vmName, InstanceViewTypes.InstanceView);
Then you can take the first NIC, get the last part of that as an ID:
var firstNic = vmResult.NetworkProfile.NetworkInterfaces.First();
var nicNameParts = firstNic.Id.Split('/');
string networkIntefaceName = nicNameParts.Last();
using (var client = new NetworkManagementClient(credential))
{
client.SubscriptionId = subscriptionId;
string publicNicId = string.Empty;
//Query ALL Networkinterfaces in the client, and find the one with the matching NIC-name
var nic = client.NetworkInterfaces.ListAll().FirstOrDefault(x => x.Name == networkIntefaceName);
if (nic != null)
{
//If we find that, we can now use that to find the ID of the PublicIPAddress for said NIC
publicNicId = nic.IpConfigurations[0].PublicIPAddress.Id;
//...And when we have that, we can now query all public IP addresses for that specific public Nic ID
var publicIp = client.PublicIPAddresses.ListAll().FirstOrDefault(x => x.Id == publicNicId);
if (publicIp != null)
{
vmInfo.PublicIP = publicIp.IpAddress;
Console.WriteLine(" public ip: " + publicIp.IpAddress);
}
else
{
Console.WriteLine(" public ip: unknown");
}
}
}
Yes, it is not super elegant, it can be optimized etc - but it works, so that's a start. :)
Related
I am trying to get the list of users in ADO using .NET clients. I am referring to this git repository:
https://github.com/microsoft/azure-devops-dotnet-samples/blob/master/ClientLibrary/Quickstarts/dotnet/GraphQuickStarts/Samples/EnumerateUsers.cs
I tried same thing but still it shows error that GetUsersAsync needs assembly reference. I have tried all the references. I am getting GetUserAsync but that is for one user. I need to fetch all the users.
Instead of using GetUsersAsync, please use ListUsersAsync:
PagedGraphUsers users = graphClient.ListUsersAsync().Result;
In the following two code samples i'm returning the users' emails. You can use Azure DevOps' userentitlements to return the information you need like the license details.
SDK
//string organization = ...
//string userName = ...
//string pat = ...
List<string> users = new List<string>();
var uri = new Uri($"https://vsaex.dev.azure.com/{organization}");
var credentials = new VssBasicCredential(userName, pat);
using (var connection = new VssConnection(uri, credentials))
using (var client = connection.GetClient<MemberEntitlementManagementHttpClient>())
{
string continuationToken = null;
do
{
var data = await client.SearchUserEntitlementsAsync(continuationToken);
continuationToken = data.ContinuationToken;
foreach (var member in data.Members)
{
string email = member.User.MailAddress.ToLower();
users.Add(email);
}
}
while (continuationToken != null);
}
Rest API
//string organization = ...
// HttpClient client = ...
List<string> users = new List<string>();
string baseUrl = $"https://vsaex.dev.azure.com/{organization}/_apis/userentitlements?api-version=6-preview.3";
string url = baseUrl;
string continuationToken = string.Empty;
do
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
dynamic data = await response.Content.ReadAsAsync<object>();
foreach (var member in data.members)
{
users.Add(member.user.mailAddress.ToString());
}
continuationToken = HttpUtility.UrlEncode(data.continuationToken.ToString());
url = baseUrl + "&continuationToken=" + continuationToken;
}
}
while (!string.IsNullOrWhiteSpace(continuationToken));
I have an API that has devices firing data to it at the same time or within a few milliseconds. What I am finding is that the data is getting mixed up. The data is sent every five minutes (on the clock 05, 10, 15 etc.) I have an execution filter that traps the URL data coming in so I always have a real source, then it goes to the endpoint and then onto processing. For example, there will a be random five minute period missing. When I debug step by step with the missing URL from the execution filter it works fine. By that I mean I take the URL and debug, then it inserts.
In summary, I have device id 1 and device id 2.I will get missing intervals even though, I can see the data has hit the execution filter.
I am assuming that the API is not handling these as separate transactions, but somehow mixing them up together, hence the data missing and the serial numbers appearing in the wrong place, such that data from id 1 is appearing in id 2 vice versa etc.
API End Point:
public class SomeController : ApiController
{
[HttpGet]
[ExecutionFilter]
public async Task<HttpResponseMessage> Get([FromUri] FixedDataModel fdm)
{
var reply = new HttpResponseMessage();
string url = HttpUtility.UrlDecode(HttpContext.Current.Request.QueryString.ToString());
if (url.Contains("timestamp"))
{
reply = TimeSyncValidation.TimeSync;
return reply;
}
else if (!url.Contains("timestamp"))
{
reply = await Task.Run(() => DeviceClass.DeviceApiAsync(fdm, url));
}
return reply;
}
}
Processing class:
namespace API.Services
{
public class DeviceClass
{
private static string serialNumber;
private static byte chk;
private static string channelName, channelReadingNumber, channelValue, queryString, readingDate;
private static int colonPosition, chanCountFrom, equalsPosition;
private static bool checkSumCorrect;
public static HttpResponseMessage DeviceApiAsync(FixedDataModel fdm, string urlQqueryString)
{
Guid guid = Guid.NewGuid();
//ExecutionTrackerHandler.Guid = guid;
//Remove question mark
var q = urlQqueryString;
queryString = q.Substring(0);
var items = HttpUtility.ParseQueryString(queryString);
serialNumber = items["se"];
//Store raw uri for fault finding
var rawUri = new List<RawUriModel>
{
new RawUriModel
{
UniqueId = guid,
RawUri = q,
TimeStamp = DateTime.Now
}
};
//Checksum validation
chk = Convert.ToByte(fdm.chk);
checkSumCorrect = CheckSumValidator.XorCheckSum(queryString, chk);
if (!checkSumCorrect)
{
return ValidationResponseMessage.ResponseHeaders("Checksum");
}
//Create list of items that exist in URL
var urldata = new UrlDataList
{
UrlData = queryString.Split('&').ToList(),
};
var data = new List<UriDataModel>();
//Split the URL string into its parts
foreach (var item in urldata.UrlData)
{
colonPosition = item.IndexOf(":");
chanCountFrom = colonPosition + 1;
equalsPosition = item.LastIndexOf("=");
if (colonPosition == -1)
{
channelName = item.Substring(0, equalsPosition);
channelReadingNumber = "";
channelValue = item.Substring(item.LastIndexOf("=") + 1);
}
else
{
channelName = item.Substring(0, colonPosition);
channelReadingNumber = item.Substring(chanCountFrom, equalsPosition - chanCountFrom);
channelValue = item.Substring(item.LastIndexOf("=") + 1);
if (channelName == "atime" || channelName == "adate")
{
readingDate = DateValidator.CreateDate(channelValue);
}
};
bool nullFlag = false;
if (channelValue == null)
nullFlag = true;
bool missingFlag = false;
if (channelValue == "x") {
missingFlag = true;
channelValue = "0";
}
//Add data to model ready for DB insert.
data.Add(new UriDataModel
{
uid = guid,
SerialNumber = serialNumber,
ChannelName = channelName,
ChannelReadingNumber = channelReadingNumber,
ChannelValue = channelValue.Replace(",", "."),
ReadingDate = readingDate,
TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm"),
Processed = false,
NullFlag = nullFlag,
MissingFlag = missingFlag
});
};
//Validate dates
var allDates = (from x in data where x.ChannelName.Contains("atime") || x.ChannelName.Contains("adate") select x.ChannelValue).ToList();
bool dateValidation = DateValidator.IsValid(allDates);
if (!dateValidation)
{
return ValidationResponseMessage.ResponseHeaders("Date");
};
//Validate values
var channels = Enum.GetNames(typeof(Channels)).ToList();
List<string> allChannelValues = data.Where(d => channels.Contains(d.ChannelName)).Select(d => d.ChannelValue).ToList();
bool valueValidation = ValueValidator.IsValid(allChannelValues);
if (!valueValidation)
{
return ValidationResponseMessage.ResponseHeaders("Values");
};
//Insert live data
var insertData = DataInsert<UriDataModel>.InsertData(data, "Staging.UriData");
if (!insertData)
{
return ValidationResponseMessage.ResponseHeaders("Sql");
}
var content = "\r\nSUCCESS\r\n";
var reply = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
Content = new StringContent(content)
};
return reply;
}
}
}
TIA
You are using global variables and static method to process your data.
Change your method to non-static.
Each DeviceClass worker must update only its own isolated data then push that off back to controller.
For Create Registration on azure notification hub
We want authorization token for below rest api
https://{namespace}.servicebus.windows.net/{NotificationHub}/registrations/?api-version=2015-01
please see follwing link
https://msdn.microsoft.com/en-us/library/azure/dn223265.aspx
// Add Nuget package
Install-Package Microsoft.Azure.NotificationHubs
using Microsoft.Azure.NotificationHubs;//Add namespace
string accessTokenstring = GetAccessToken();
private string GetAccessToken()
{
var hubName = "<Notification Hub>";
string connectionString = "Endpoint=sb://<Notification Hub Namespace>.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=<Key>";
var apiVersion = "?api-version=2015-01";
string endpoint = null;
string sasKeyValue = null;
string sasKeyName = null;
string targetUri = null;
var parts = connectionString.Split(';');
foreach (var part in parts)
{
if (part.IndexOf("Endpoint") == 0)
{
endpoint = "https" + part.Substring(11);
}
else if (part.IndexOf("SharedAccessKeyName") == 0)
{
sasKeyName = part.Substring(20);
}
else if (part.IndexOf("SharedAccessKey") == 0)
{
sasKeyValue = part.Substring(16);
}
}
targetUri = endpoint + hubName;
var registrationPath = targetUri + "/Registrations/";
var resourceUri = registrationPath + apiVersion;
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
string accessTokenstring = SharedAccessSignatureTokenProvider.GetSharedAccessSignature(sasKeyName, sasKeyValue, resourceUri, sinceEpoch);
return accessTokenstring;
}
Trying to follow Direct Send (https://msdn.microsoft.com/en-us/library/mt608572.aspx) I faced the same problem.
I was able to use #Sama's solution just changing the "Registrations" to "messages". The Solution provided is working in .Net Core.
I am trying to connect with c#.
Here is the class that submits hive queries successfully to my remote HDInsight cluster. what do i need to change here to connect to the local emulator
public class HadoopImporter : IImporter
{
public static readonly Logger log = LogManager.GetCurrentClassLogger();
public void Import(string _query)
{
try
{
log.Warn("Inside Hive submission method");
var store = new X509Store();
store.Open(OpenFlags.ReadOnly);
var cert =
store.Certificates.Cast<X509Certificate2>()
.First(item => item.Thumbprint == "MYCERTTUMBPRINT");
if (cert == null)
log.Error("no cert found");
log.Warn(cert.FriendlyName);
log.Warn("got the cert with thumbprint ", cert.Thumbprint.ToString())
;
log.Warn("trying to create credentials from cert");
var creds = new JobSubmissionCertificateCredential(new Guid("MYSUBSCRIPTIONID"),
cert, "MYSTORAGECONTAINER");
log.Warn("trying to connect with cert");
var jobClient = JobSubmissionClientFactory.Connect(creds);
log.Warn("Setting Hive job parameters");
var hiveJob = new HiveJobCreateParameters()
{
Query = _query,
StatusFolder = "/samplequeryoutput"
};
var jobResults = jobClient.CreateHiveJob(hiveJob);
log.Warn("Executing wait for jhive results");
WaitForJobCompletion(jobResults, jobClient);
using (var stream = jobClient.GetJobOutput(jobResults.JobId))
{
var reader = new StreamReader(stream);
var res = reader.ReadToEnd();
log.Warn("trying to get the job results " + res.ToString());
}
}
catch (Exception exp)
{
log.Error(exp);
}
}
private static void WaitForJobCompletion(JobCreationResults jobDetails, IJobSubmissionClient client)
{
var jobInProgress = client.GetJob(jobDetails.JobId);
while (jobInProgress.StatusCode != JobStatusCode.Completed && jobInProgress.StatusCode != JobStatusCode.Failed)
{
log.Warn("Inside the while loop waiting for hive job to complete");
jobInProgress = client.GetJob(jobInProgress.JobId);
Thread.Sleep(TimeSpan.FromSeconds(10));
}
log.Trace("HIVE Job has Imported " + jobDetails.JobId);
}
}
You should be able to connect to a local one-box using the REST implementation of the client.
You're looking for the WebHCatHttpClient interface. The code below runs a basic query against my local one-box.
var httpClient = new WebHCatHttpClient(new Uri("http://localhost:50111/"), "username", "password");
string outputDir = "basichivejob";
var task = httpClient.CreateHiveJob(#"select * from iris;", null, null, outputDir, null);
task.Wait();
var response = task.Result;
var output = response.Content.ReadAsAsync<JObject>();
output.Wait();
response.EnsureSuccessStatusCode();
string id = output.Result.GetValue("id").ToString();
httpClient.WaitForJobToCompleteAsync(id).Wait();
See the SDK docs for more info.
I use DotNetOpenAuth.
So.. I am getting looking good response which has state Authenticated.
That is fine.
Now I want to get user profile info but always getting NULL.
Here is the code.
private ServiceProviderDescription GetServiceDescription()
{
string ValidateTokenEndPoint = ConfigurationManager.AppSettings["identityOAuthValidateTokenEndPointUrl"];
string ValidateAuthorizationHeaderEndPoint = ConfigurationManager.AppSettings["identityOAuthValidateAuthorizationHeaderEndPointUrl"];
string AccessTokenEndPoint = ConfigurationManager.AppSettings["identityOAuthAccessTokenURL"];
bool UseVersion10A = Convert.ToBoolean(ConfigurationManager.AppSettings["identityOAuthUseVersion10a"]);
string RequestTokenStr = ConfigurationManager.AppSettings["identityOAuthRequestTokenURL"];
string UserAuthStr = ConfigurationManager.AppSettings["identityOAuthAuthorizeUserURL"];
string AccessTokenStr = ConfigurationManager.AppSettings["identityOAuthAccessTokenURL"];
string InvalidateTokenStr = ConfigurationManager.AppSettings["identityOAuthRequestInvalidateTokenURL"];
return new ServiceProviderDescription
{
AccessTokenEndpoint = new MessageReceivingEndpoint(AccessTokenStr, HttpDeliveryMethods.PostRequest),
RequestTokenEndpoint = new MessageReceivingEndpoint(RequestTokenStr, HttpDeliveryMethods.PostRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint(UserAuthStr, HttpDeliveryMethods.PostRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
ProtocolVersion = DotNetOpenAuth.OAuth.ProtocolVersion.V10a
};
}
void GetUserProfile()
{
var tokenManager = TokenManagerFactory.GetTokenManager(TokenManagerType.InMemoryTokenManager);
tokenManager.ConsumerKey = ConfigurationManager.AppSettings["identityOAuthConsumerKey"];
tokenManager.ConsumerSecret = ConfigurationManager.AppSettings["identityOAuthConsumerSecret"];
var serviceDescription = GetServiceDescription();
var consumer = new WebConsumer(serviceDescription, tokenManager);
var result = consumer.ProcessUserAuthorization(response);
if (result != null) // It is always null
{
}
Well I checked 10 times and I am pretty sure that all URLs to create ServiceProviderDescription are correct.
Any clue?
Well
finally check your web.config app keys
add key="identityOAuthConsumerKey" value="put here correct data!!!"
add key="identityOAuthConsumerSecret" value="put here correct data!!!"
and if you use hosts file you have to put correct sitename as well
127.0.0.1 site1.host1.com