Azure Virtual Machine has no endpoint - c#

Im trying to create VM's from a template in my ASP.NET MVC web application. So I wrote an action is structured in 4 steps (I added some comments to make it more understandable)
[HttpPost]
public ActionResult QuickCreateVM(string VirtualMachineName, string OSImage, string Username, string Password)
{
string Location = "North Europe";
string StorageAccountName = "azuremanagersharepoint";
try
{
ComputeManagementClient client = new ComputeManagementClient(cloudCredentials);
string vmName = VirtualMachineName;
//STEP1:Create Hosted Service
//Azure VM must be hosted in a hosted cloud service.
createCloudService(vmName, Location);
//STEP2:Construct VM Role instance
var vmRole = new Role();
vmRole.RoleType = VirtualMachineRoleType.PersistentVMRole.ToString();
vmRole.RoleName = vmName;
vmRole.Label = vmName;
vmRole.RoleSize = VirtualMachineRoleSize.Small;
vmRole.ConfigurationSets = new List<ConfigurationSet>();
vmRole.OSVirtualHardDisk = new OSVirtualHardDisk()
{
MediaLink = getVhdUri(string.Format("{0}.blob.core.windows.net/uploads", StorageAccountName)),
SourceImageName = OSImage
};
ConfigurationSet configSet = new ConfigurationSet
{
ConfigurationSetType = ConfigurationSetTypes.WindowsProvisioningConfiguration,
EnableAutomaticUpdates = true,
ResetPasswordOnFirstLogon = false,
ComputerName = vmName,
AdminUserName = Username,
AdminPassword = Password,
InputEndpoints = new BindingList<InputEndpoint>
{
new InputEndpoint { LocalPort = 3389, Port = 3389, Name = "Remote Desktop", Protocol = "TCP", EnableDirectServerReturn = true }
}
};
vmRole.ConfigurationSets.Add(configSet);
vmRole.ResourceExtensionReferences = null;
//STEP3: Add Role instance to Deployment Parmeters
List<Role> roleList = new List<Role>() { vmRole };
VirtualMachineCreateDeploymentParameters createDeploymentParams = new VirtualMachineCreateDeploymentParameters
{
Name = vmName,
Label = vmName,
Roles = roleList,
DeploymentSlot = DeploymentSlot.Production
};
//STEP4: Create a Deployment with VM Roles.
client.VirtualMachines.CreateDeployment(vmName, createDeploymentParams);
}
catch (CloudException e)
{
throw e;
}
catch (Exception ex)
{
throw ex;
}
return View("Panel");
}
My problem: It seems like my VM has no endpoint. Although the ConfigurationSet was configured correctly. So, in my code I say
new InputEndpoint { LocalPort = 3389, Port = 3388, Name = "Remote Desktop", Protocol = "TCP", EnableDirectServerReturn = true }
But in the azure portal
So I'm not able to start the Vm.
Has anyone an idea what I'm missing? Or are there any good tutorials to this topic?
Thank you in advance

Ok, so I had the exact same issue and figured out the problem.
You need to create an additional ConfigurationSet with a ConfigurationSetType of ConfigurationSetTypes.NetworkConfiguration, and then add your endpoints in there.
Something like this:
ConfigurationSet networkConfigSet = new ConfigurationSet
{
ConfigurationSetType = ConfigurationSetTypes.NetworkConfiguration,
InputEndpoints = new BindingList<InputEndpoint>
{
new InputEndpoint { LocalPort = 3389, Port = 3389, Name = "Remote Desktop", Protocol = "TCP", EnableDirectServerReturn = true }
}
};
vmRole.ConfigurationSets.Add(networkConfigSet);
See here:
https://msdn.microsoft.com/en-us/library/azure/jj157194.aspx
...specifically the ConfigurationSets section.

Related

vSphere VMware.Vim Clone_VM 'The operation is not allowed in the current state.'

My team is developing an application that needs to clone existing templates in our vSphere environment. We're using VMware.Vim in a C# application to do this. We're replacing an already existing implementation that uses PowerShell.
Below is the code that is throwing the error. We are eventually going to load balance based on memory usage, but currently we are selecting the host by random. That's why there is some extra code with collecting all of the hosts and then picking one.
When it gets to CloneVM_Task, an exception with the message 'The operation is not allowed in the current state.' is thrown. The exception doesn't give me much to work with and I can't find any useful logs in vSphere. vSphere just says "An error prevented the virtual machine from being cloned" in the events log. We're using version 6.7. I'm new to VMWare, so any help is appreciated. Their documentation is lacking, to say the least.
public async void CreateVirtualMachineAsync(NewVMRequest newVMRequest)
{
var appliance = await _applianceService.GetAppliance(newVMRequest.Appliance);
var vimClient = new VimClientImpl
{
IgnoreServerCertificateErrors = true, ServiceUrl = appliance.ServiceUrl
};
vimClient.Login(appliance.User, appliance.Password);
var datacenter = GetDatacenter(vimClient);
var hostCollection = GetListOfHosts(vimClient, datacenter);
var randomHost = PickRandomHost(hostCollection);
var sourceVm = GetSelectedVm(vimClient, newVMRequest);
if (sourceVm == null)
{
_logger.LogDebug($"Could not find virtual machine {newVMRequest.Source} to use for template");
_logger.LogError($"Could not find virtual machine {newVMRequest.Source} to use for template", null);
return;
}
var selectedStore = ConnectToDataStore(vimClient);
var cluster = GetCluster(vimClient);
var mySpec = CreateCloneSpec(selectedStore, randomHost, cluster, sourceVm);
vimClient.WaitForTask(sourceVm.CloneVM_Task(sourceVm.Parent, newVMRequest.Name, mySpec));
vimClient.Disconnect();
}
private VirtualMachineCloneSpec CreateCloneSpec(Datastore selectedStore, ManagedObjectReference randomHost, ClusterComputeResource cluster, VirtualMachine sourceVm)
{
var mySpec = new VirtualMachineCloneSpec
{
Location = new VirtualMachineRelocateSpec
{
Datastore = selectedStore.MoRef,
Transform = VirtualMachineRelocateTransformation.sparse,
Host = randomHost,
Pool = cluster.ResourcePool
},
Config = new VirtualMachineConfigSpec()
};
var networkDevice = new VirtualDevice();
foreach (var vDevice in sourceVm.Config.Hardware.Device)
{
if (vDevice.DeviceInfo.Label.Contains("Network"))
{
networkDevice = vDevice;
}
}
var devSpec = new VirtualDeviceConfigSpec
{
Device = networkDevice, FileOperation = VirtualDeviceConfigSpecFileOperation.create
};
mySpec.Config.DeviceChange = new[] { devSpec };
return mySpec;
}
private Datacenter GetDatacenter(VimClient vimClient)
{
var entities = vimClient.FindEntityViews(typeof(Datacenter), null, null, null);
return (Datacenter)entities.First();
}
private List<ManagedObjectReference> GetListOfHosts(VimClient vimClient, Datacenter datacenter)
{
var hostCollection = new List<ManagedObjectReference>();
var hostFolderMoRef = datacenter.HostFolder;
var hostFolder = (Folder)vimClient.GetView(hostFolderMoRef, null);
var childEntityMoRefs = hostFolder.ChildEntity;
foreach (var childEntityMoRef in childEntityMoRefs)
{
var thisCluster = (ClusterComputeResource)vimClient.GetView(childEntityMoRef, null);
var clusterHostMoRefs = thisCluster.Host;
foreach (var clusterHostMoRef in clusterHostMoRefs)
{
var hostSystem = (HostSystem)vimClient.GetView(clusterHostMoRef, null);
hostCollection.Add(hostSystem.MoRef);
}
}
return hostCollection;
}
private ManagedObjectReference PickRandomHost(List<ManagedObjectReference> hostCollection)
{
var rand = new Random();
return hostCollection[rand.Next(0, hostCollection.Count)];
}
private VirtualMachine GetSelectedVm(VimClient vimClient, NewVMRequest newVMRequest)
{
var filter = new NameValueCollection
{
{"name", newVMRequest.Source},
{"Config.Template", newVMRequest.UseTemplate.ToString().ToLower()}
};
var entityViews = vimClient.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, filter, null);
if (entityViews.Count == 0)
{
return null;
}
return (VirtualMachine)vimClient.FindEntityViews(typeof(VMware.Vim.VirtualMachine), null, filter, null).First();
}
private Datastore ConnectToDataStore(VimClient vimClient)
{
var myDs = vimClient.FindEntityView(typeof(Datastore), null, null /*dsFilter*/, null);
return (Datastore)myDs;
}
private ClusterComputeResource GetCluster(VimClient vimClient)
{
var appClusters = vimClient.FindEntityViews(typeof(ClusterComputeResource), null, null, null);
return (ClusterComputeResource)appClusters?.FirstOrDefault();
}
For the most part, your code looks good. I would suggest changing the spec file and using the least possible information to create a clone from existing template. Once you have success, you can add more details and see if that errors out.
Start off with this and see if this gets you going.
private VirtualMachineCloneSpec CreateCloneSpec(Datastore selectedStore, ManagedObjectReference randomHost, ClusterComputeResource cluster, VirtualMachine sourceVm)
{
var mySpec = new VirtualMachineCloneSpec
{
Location = new VirtualMachineRelocateSpec
{
Datastore = selectedStore.MoRef,
Host = randomHost,
Pool = cluster.ResourcePool
},
PowerOn = false,
Template = false
};
return mySpec;
}
If the above goes through, then add the VirtualMachineRelocateTransformation to transform your thick VM as thin VM and network connections as needed.

Exchange Web Services SMTP address error : ErrorNonExistentMailbox

Please i use a service windows to acced to my email. i have this exception when i try to bind my folder
Here is my code
private static readonly ExchangeVersion _ExchangeServerVersion = ExchangeVersion.Exchange2010;
private static readonly IWebProxy _ExchangeWebProxy;
public static EmailClient CreateClient(string account, string password, string domain, string mailtowatch=null ,TimeSpan? timeout = null )
{
if (!timeout.HasValue)
{
timeout = new TimeSpan(0, 5, 0);
}
EmailClient result = new EmailClient();
result.Mailbox = mailtowatch;
ExchangeService client = new ExchangeService(_ExchangeServerVersion);
client.UseDefaultCredentials = true;
if (!string.IsNullOrEmpty(password))
{
client.Credentials = new WebCredentials(account, password, domain);
}
try
{
client.AutodiscoverUrl(mailtowatch);
}
catch (Exception)
{
client.Url = new Uri("https://office.natixis.com/EWS/Exchange.asmx");
}
client.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, mailtowatch);
client.WebProxy = WebRequest.DefaultWebProxy;
client.WebProxy = _ExchangeWebProxy;
result.Service = client;
client.Timeout = (int)(timeout.Value.TotalMilliseconds);
return result;
}
*******************************
and i call it here
*******************************
Folder folder = null;
FolderId id = null;
if (criteria.FolderName != null)
{
log.Debug(string.Format("Getting folder {0}", criteria.FolderName));
id = GetFolderId(criteria.FolderName);
}
log.Debug("Start binding folder");
if (criteria.Password == null)
{
var folderTemp = new FolderId(WellKnownFolderName.Inbox, criteria.EmailToWatch); //Or the folder you want to search in
folder = Folder.Bind(Service, folderTemp);
}
else
{
//client.UseDefaultCredentials = true;
folder = Folder.Bind(Service, id ?? new FolderId(WellKnownFolderName.Inbox, new Mailbox( criteria.EmailToWatch) ));
}
but on bindid the folder i have an exception ErrorNonExistentMailbox.
Even when i use UseDefaultCredentials = true is not working

How to create AutoScale Settings programmatically with C# for Windows Azure Web App using Microsoft.WindowsAzure.Management.Monitoring?

What Do I have:
var subscriptionId = "xxx";
var thumbprint = "xxx";
var certificate = GetCertificate(StoreName.My, StoreLocation.CurrentUser, thumbprint);
var autoscaleClient = new AutoscaleClient(new CertificateCloudCredentials(subscriptionId, certificate));
var createParams = new AutoscaleSettingCreateOrUpdateParameters
{
Setting = new AutoscaleSetting
{
Enabled = true,
Profiles = new List<AutoscaleProfile>
{
new AutoscaleProfile
{
Capacity = new ScaleCapacity
{
Default ="1",
Maximum="10",
Minimum="1"
},
Name = "anurag",
Recurrence= new Recurrence
{
Frequency=RecurrenceFrequency.Week,
Schedule = new RecurrentSchedule
{
Days = new List<string>{"Monday", "Thursday", "Friday"},
Hours = {7, 19},
Minutes=new List<int>{0},
TimeZone = "Pacific Standard Time"
}
},
Rules=new List<ScaleRule>
{
new ScaleRule
{
MetricTrigger =new MetricTrigger
{
MetricName="Test Metric",
MetricNamespace="",
MetricSource=
AutoscaleMetricSourceBuilder.BuildWebSiteMetricSource("???", "???"),
Operator=ComparisonOperationType.GreaterThan,
Threshold=2000,
Statistic=MetricStatisticType.Average,
TimeGrain=TimeSpan.FromMinutes(5),
TimeAggregation=TimeAggregationType.Average,
TimeWindow=TimeSpan.FromMinutes(30)
},
ScaleAction = new ScaleAction
{
Direction = ScaleDirection.Increase,
Cooldown = TimeSpan.FromMinutes(20),
Type=ScaleType.ChangeCount,
Value = "4"
}
}
}
}
}
}
};
var resourceId = AutoscaleResourceIdBuilder.BuildWebSiteResourceId("???", "???");
var autoscaleResponse = autoscaleClient.Settings.CreateOrUpdate(resourceId, createParams);
I am confused about two API calls:
AutoscaleResourceIdBuilder.BuildWebSiteResourceId(string webspace, string serverFarmName)
AutoscaleMetricSourceBuilder.BuildWebSiteMetricSource(string webspaceName, string websiteName)
What is a webspace, server farm name, webspace name and web site name? Where Do I get them?

Controller is returning blank View in my website

public async Task<IActionResult> Contact1()
{
if (Convert.ToBoolean(HttpContext.Session.GetString("login")))
{
var pass = new ContactViewModel();
var username = HttpContext.Session.GetString("username");
Program.readname(HttpContext.Session.GetString("username"));
var names = HttpContext.Session.GetString("studentnames");
var obj1 = JsonConvert.DeserializeObject<Program.Data>(names);
if (Program.datecheck(username, DateTime.Today.Date))
{
try{
var handler = new HttpClientHandler { Credentials = new NetworkCredential(user, password) };
using (var client = Program.CreateHttpClient(handler, user, database3))
{
string check = username + Convert.ToString(DateTime.Today.Date);
var readresponse = client.GetStringAsync(check).Result;
var obj2 = JsonConvert.DeserializeObject<Program.Data>(readresponse);
}
catch(Exception ee)
{ ViewBag.m6 = ee.Message; ViewBag.attendance = "Attendace is not take yet";}
}
pass.studentattend = obj2.studentattend1;
}
}
else { ViewBag.attendance = "Attendace is not take yet"; }
pass.studentname = obj1.studentname1;
pass.studentrollno = obj1.studentrollno1;
pass.date = DateTime.Today.Date;
HttpContext.Session.SetInt32("classselect", 1);
ViewData["Message"] = "Student Attendance of Class: " + HttpContext.Session.GetString("classname1");
ViewBag.Login = HttpContext.Session.GetString("login");
ViewBag.name = HttpContext.Session.GetString("name");
ViewBag.classname1 = HttpContext.Session.GetString("classname1");
ViewBag.classname2 = HttpContext.Session.GetString("classname2");
ViewBag.classname3 = HttpContext.Session.GetString("classname3");
ViewBag.classname4 = HttpContext.Session.GetString("classname4");
return View("/Views/Home/Contact.cshtml", pass);
}
else
{
ViewData["Message"] = "Please Login First!!";
return View("/Views/Home/Login.cshtml");
}
}
The above code is runnig well in my local ISS server but when i run this on bluemix then i am getting blank page. I tried to find out the problem and get to the conclusion that if the control does not enter in the if part of that code:
if (Program.datecheck(username, DateTime.Today.Date))
{
var handler = new HttpClientHandler { Credentials = new NetworkCredential(user, password) };
using (var client = Program.CreateHttpClient(handler, user, database3))
{
string check = username + Convert.ToString(DateTime.Today.Date);
var readresponse = client.GetStringAsync(check).Result;
var obj2 = JsonConvert.DeserializeObject<Program.Data>(readresponse);
pass.studentattend = obj2.studentattend1;
}
}
else { ViewBag.attendance = "Attendace is not take yet"; }
then it will run fine.I am unable to find what is wrong in that query.

Programmatically create a web site in IIS using C# and set port number

We have been able to create a web site. We did this using the information in this link:
https://msdn.microsoft.com/en-us/library/ms525598.aspx
However, we would like to use a port number other that port 80. How do we do this?
We are using IIS 6
If you're using IIS 7, there is a new managed API called Microsoft.Web.Administration
An example from the above blog post:
ServerManager iisManager = new ServerManager();
iisManager.Sites.Add("NewSite", "http", "*:8080:", "d:\\MySite");
iisManager.CommitChanges();
If you're using IIS 6 and want to do this, it's more complex unfortunately.
You will have to create a web service on every server, a web service that handles the creation of a website because direct user impersonation over the network won't work properly (If I recall this correctly).
You will have to use Interop Services and do something similar to this (This example uses two objects, server and site, which are instances of custom classes that store a server's and site's configuration):
string metabasePath = "IIS://" + server.ComputerName + "/W3SVC";
DirectoryEntry w3svc = new DirectoryEntry(metabasePath, server.Username, server.Password);
string serverBindings = ":80:" + site.HostName;
string homeDirectory = server.WWWRootPath + "\\" + site.FolderName;
object[] newSite = new object[] { site.Name, new object[] { serverBindings }, homeDirectory };
object websiteId = (object)w3svc.Invoke("CreateNewSite", newSite);
// Returns the Website ID from the Metabase
int id = (int)websiteId;
See more here
Heres the solution.
Blog article : How to add new website in IIS 7
On Button click :
try
{
ServerManager serverMgr = new ServerManager();
string strWebsitename = txtwebsitename.Text; // abc
string strApplicationPool = "DefaultAppPool"; // set your deafultpool :4.0 in IIS
string strhostname = txthostname.Text; //abc.com
string stripaddress = txtipaddress.Text;// ip address
string bindinginfo = stripaddress + ":80:" + strhostname;
//check if website name already exists in IIS
Boolean bWebsite = IsWebsiteExists(strWebsitename);
if (!bWebsite)
{
Site mySite = serverMgr.Sites.Add(strWebsitename.ToString(), "http", bindinginfo, "C:\\inetpub\\wwwroot\\yourWebsite");
mySite.ApplicationDefaults.ApplicationPoolName = strApplicationPool;
mySite.TraceFailedRequestsLogging.Enabled = true;
mySite.TraceFailedRequestsLogging.Directory = "C:\\inetpub\\customfolder\\site";
serverMgr.CommitChanges();
lblmsg.Text = "New website " + strWebsitename + " added sucessfully";
}
else
{
lblmsg.Text = "Name should be unique, " + strWebsitename + " is already exists. ";
}
}
catch (Exception ae)
{
Response.Redirect(ae.Message);
}
Looping over sites whether name already exists
public bool IsWebsiteExists(string strWebsitename)
{
Boolean flagset = false;
SiteCollection sitecollection = serverMgr.Sites;
foreach (Site site in sitecollection)
{
if (site.Name == strWebsitename.ToString())
{
flagset = true;
break;
}
else
{
flagset = false;
}
}
return flagset;
}
Try the following Code to Know the unUsed PortNo
DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
// Find unused ID PortNo for new web site
bool found_valid_port_no = false;
int random_port_no = 1;
do
{
bool regenerate_port_no = false;
System.Random random_generator = new Random();
random_port_no = random_generator.Next(9000,15000);
foreach (DirectoryEntry e in root.Children)
{
if (e.SchemaClassName == "IIsWebServer")
{
int site_id = Convert.ToInt32(e.Name);
//For each detected ID find the port Number
DirectoryEntry vRoot = new DirectoryEntry("IIS://localhost/W3SVC/" + site_id);
PropertyValueCollection pvcServerBindings = vRoot.Properties["serverbindings"];
String bindings = pvcServerBindings.Value.ToString().Replace(":", "");
int port_no = Convert.ToInt32(bindings);
if (port_no == random_port_no)
{
regenerate_port_no = true;
break;
}
}
}
found_valid_port_no = !regenerate_port_no;
} while (!found_valid_port_no);
int newportId = random_port_no;
I have gone though all answer here and also tested. Here is the most clean smarter version of answer for this question. However this still cant work on IIS 6.0. so IIS 8.0 or above is required.
string domainName = "";
string appPoolName = "";
string webFiles = "C:\\Users\\John\\Desktop\\New Folder";
if (IsWebsiteExists(domainName) == false)
{
ServerManager iisManager = new ServerManager();
iisManager.Sites.Add(domainName, "http", "*:8080:", webFiles);
iisManager.ApplicationDefaults.ApplicationPoolName = appPoolName;
iisManager.CommitChanges();
}
else
{
Console.WriteLine("Name Exists already");
}
public static bool IsWebsiteExists(string strWebsitename)
{
ServerManager serverMgr = new ServerManager();
Boolean flagset = false;
SiteCollection sitecollection = serverMgr.Sites;
flagset = sitecollection.Any(x => x.Name == strWebsitename);
return flagset;
}
This simplified method will create a site with default binding settings, and also create the application pool if needed:
public void addIISApplication(string siteName, string physicalPath, int port, string appPoolName)
{
using (var serverMgr = new ServerManager())
{
var sitecollection = serverMgr.Sites;
if (!sitecollection.Any(x => x.Name.ToLower() == siteName.ToLower()))
{
var appPools = serverMgr.ApplicationPools;
if (!appPools.Any(x => x.Name.ToLower() == appPoolName.ToLower()))
{
serverMgr.ApplicationPools.Add(appPoolName);
}
var mySite = serverMgr.Sites.Add(siteName, physicalPath, port);
mySite.ApplicationDefaults.ApplicationPoolName = appPoolName;
serverMgr.CommitChanges();
}
}
}
In properties of site select "Web Site" tab and specify TCP Port.
In studio to debug purpose specify http://localhost:<port>/<site> at tab Web for "Use Local IIS Web Server"

Categories

Resources