最近在windows Azure上做一个项目,需要动态管理虚拟机。在实际开发的时候发现网上的资料还是很少的,下面把自己用到的一些共享出来
AzureHelpter.cs :
public class AzureHelpter
{
private string subscriptionID;
private string cloudServiceName;
private string storageAccountName;
private string certThumb;
private string depName;//vm depname
private string role;//vm name
private string disk;//vm disk
private string medialink;//vm medialink
private string accont;
private string computerName;
private string acccont;
private string requestId;
public AzureHelpter(string accont)
{
this.acccont = accont;
var userInfo = new EntityControl().Session.QueryOver()
.Where(m => m.Cloud_UserAccont == accont)
.SingleOrDefault();
if (userInfo == null)
throw new Exception(string.Format("未能获取{0}的用户信息", accont));
var serviceInfo = new EntityControl().Session.QueryOver()
.Where(m => m.Cloud_ServiceAccont == accont)
.SingleOrDefault();
if (serviceInfo == null)
throw new Exception(string.Format("未能获取{0}的用户服务信息", accont));
this.accont = accont;
subscriptionID = Config.GetConifgValue("subscriptionID", "");
storageAccountName = Config.GetConifgValue("storageAccountName", "");
certThumb = Config.GetConifgValue("certThumb", "");
cloudServiceName = "EDoc2Service" + userInfo.Cloud_UserCompanyShortName;
depName = "EDoc2Dep" + userInfo.Cloud_UserCompanyShortName;
role = "EDoc2Role" + userInfo.Cloud_UserCompanyShortName;
disk = "EDoc2Disk" + userInfo.Cloud_UserCompanyShortName;
medialink = "EDoc2Medialink" + userInfo.Cloud_UserCompanyShortName;
computerName = "Edoc2" + userInfo.Cloud_UserCompanyShortName;
requestId = serviceInfo.Cloud_VmRequestId;
}
///
/// 创建云服务 约束:云服务名=EDoc2Service+accont 只能是英文和数字.长度也不要太长
///
///
public bool CreateSevice()
{
var requestId = "";
var result = new MgmtHelper().Request(out requestId, string.Format("https://management.core.windows.net/{0}/services/hostedservices",
subscriptionID),
"application/xml",
"2010-10-28",
ReadConfig("CreateCS.xml"),
certThumb);
LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("尝试创建云服务{0}:返回{1}", role, result));
var createResult = result.IndexOf("Created") >= 0;
return createResult;
}
///
/// 创建虚拟机
/// out string requestId
///
public bool CreateVmFromImg(out string requestId)
{
var xml = ReadConfig("CreateFromImage.xml");
var pswd = MakeRandomPassword("NUMCHAR", 9);
xml = xml.Replace("{EdocPswd}", "Edoc21234");
var result = new MgmtHelper().Request(out requestId, string.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments",
subscriptionID,
cloudServiceName),
"application/xml",
"2012-03-01",
xml,
certThumb);
LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("尝试创建虚拟机{0}:返回{1}", role, result));
var createResult = result.IndexOf("Accepted") >= 0;
if (createResult == true)
{
var serviceInfo = new EntityControl().Session.QueryOver()
.Where(m => m.Cloud_ServiceAccont == accont)
.SingleOrDefault();
if (serviceInfo == null)
{
LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("未能获取到账号{0}的服务信息", role));
return false;
}
serviceInfo.Cloud_ServiceAzurePassword = pswd;
new EntityControl().UpdateEntity(serviceInfo);
}
return createResult;
}
///
/// 关闭虚拟机
///
///
public bool ShutDownVM()
{
var requestId = "";
string url = string.Format(
"https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roleinstances/{3}/Operations"
, subscriptionID
, cloudServiceName
, depName
, role);
var result = new MgmtHelper().Request(out requestId, url,
"application/xml",
" 2012-03-01",
ReadConfig("Shutdown.xml"),
certThumb);
LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("尝试关闭虚拟机{0}:返回{1}", role, result));
return result.IndexOf("Accepted") >= 0;
}
///
/// 获去虚拟机运行状态 (约定原则) Started/Stopped/Starting 目前已知的状态
///
///
public string GetVmPowerState()
{
var requestId = "";
string url = string.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}",
subscriptionID,
cloudServiceName,
depName);
var result = new MgmtHelper().Request(out requestId, url,
null,
"2012-03-01",
null,
certThumb,
"GET");
if (result.IndexOf("RoleInstance") >= 0)//存在vm实例
{
try
{
var regGlass = new Regex("(?.*?) ", RegexOptions.Singleline);
var returnValue = regGlass.Match(result).Result("${data}"); //虚拟机的运行状态 Started Stopped
// LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("尝试获取Deployment信息{0}:返回{1}", cloudServiceName, returnValue));
return returnValue;
}
catch (Exception ex)
{
LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("尝试获取Deployment信息{0}:异常了:{1}", cloudServiceName, ex.ToString()));
return "-";
}
}
return "-";//状态不明
}
///
/// 修改虚拟机
///
///
public bool StartVm()
{
var requestId = "";
string url = string.Format(
"https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments/{2}/roleinstances/{3}/Operations"
, subscriptionID
, cloudServiceName
, depName
, role);
var result = new MgmtHelper().Request(out requestId,
url,
"application/xml",
"2012-03-01",
ReadConfig("StartRole.xml"),
certThumb);
LogHelper.Instance.WriteFileLog(ErrorLevel.Little, string.Format("尝试启动虚拟机{0}:返回{1}", role, result));
return result.IndexOf("Accepted") >= 0;
}
private string ReadConfig(string filename)
{
var tempPath = AppDomain.CurrentDomain.BaseDirectory;
if (tempPath.Contains("ConsoleServer"))
{
tempPath = Path.Combine(tempPath.Substring(0, tempPath.LastIndexOf("EDoc2.ConsoleServer")), "cfg\\" + filename);
}
else
{
tempPath = Path.Combine(tempPath.Substring(0, tempPath.LastIndexOf("Edoc.Cloud")), "cfg\\" + filename);
}
using (var sr = new StreamReader(tempPath))
{
return sr.ReadToEnd().Replace("{STORAGE}", storageAccountName)
.Replace("{CSName}", cloudServiceName)
.Replace("{EDoc2Dep}", depName)
.Replace("{EDoc2Role}", role)
.Replace("{EDoc2Disk}", disk)
.Replace("{EDoc2Medialink}", medialink)
.Replace("{EDoc2ComputerName}", computerName)
.Replace("{LABEL}",
Convert.ToBase64String(
Encoding.ASCII.GetBytes(
String.Format("label{0}", DateTime.Now.ToString("yyyyMMddHHmmss")))));
}
}
///
/// 生成各类随机密码,包括纯字母,纯数字,带特殊字符等,除非字母大写密码类型,其余方式都将采用小写密码 ,至少符合Edoc21234
///
/// 密码类型 大写为"UPPER",小写为"LOWER",数字为"NUMBER",字母与数字为"NUMCHAR",数字字母字符都包括为"ALL"
/// 密码长度,最小为6位
///
private static string MakeRandomPassword(string pwdType, int length)
{
//定义密码字符的范围,小写,大写字母,数字以及特殊字符
var lowerChars = "abcdefghijklmnopqrstuvwxyz";
var upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var numnberChars = "0123456789";
var specialCahrs = "~!@#$%^&*()_+|-=,./[]{}:;':"; //"\" 转义字符不添加 "号不添加
var tmpStr = "";
int iRandNum;
var rnd = new Random();
length = (length < 6) ? 6 : length; //密码长度必须大于6,否则自动取6
// LOWER为小写 UPPER为大写 NUMBER为数字 NUMCHAR为数字和字母 ALL全部包含 五种方式
//只有当选择UPPER才会有大写字母产生,其余方式中的字母都为小写,避免有些时候字母不区分大小写
if (pwdType == "LOWER")
{
for (int i = 0; i < length; i++)
{
iRandNum = rnd.Next(lowerChars.Length);
tmpStr += lowerChars[iRandNum];
}
}
else if (pwdType == "UPPER")
{
for (int i = 0; i < length; i++)
{
iRandNum = rnd.Next(upperChars.Length);
tmpStr += upperChars[iRandNum];
}
}
else if (pwdType == "NUMBER")
{
for (int i = 0; i < length; i++)
{
iRandNum = rnd.Next(numnberChars.Length);
tmpStr += numnberChars[iRandNum];
}
}
else if (pwdType == "NUMCHAR")
{
int numLength = rnd.Next(length);
//去掉随机数为0的情况
if (numLength == 0)
{
numLength = 1;
}
int charLength = length - numLength;
string rndStr = "";
for (int i = 0; i < numLength; i++)
{
iRandNum = rnd.Next(numnberChars.Length);
tmpStr += numnberChars[iRandNum];
}
for (int i = 0; i < charLength; i++)
{
iRandNum = rnd.Next(lowerChars.Length);
tmpStr += lowerChars[iRandNum];
}
//将取得的字符串随机打乱
for (int i = 0; i < length; i++)
{
int n = rnd.Next(tmpStr.Length);
//去除n随机为0的情况
//n = (n == 0) ? 1 : n;
rndStr += tmpStr[n];
tmpStr = tmpStr.Remove(n, 1);
}
tmpStr = rndStr;
}
else if (pwdType == "ALL")
{
int numLength = rnd.Next(length - 1);
//去掉随机数为0的情况
if (numLength == 0)
{
numLength = 1;
}
int charLength = rnd.Next(length - numLength);
if (charLength == 0)
{
charLength = 1;
}
int specCharLength = length - numLength - charLength;
string rndStr = "";
for (int i = 0; i < numLength; i++)
{
iRandNum = rnd.Next(numnberChars.Length);
tmpStr += numnberChars[iRandNum];
}
for (int i = 0; i < charLength; i++)
{
iRandNum = rnd.Next(lowerChars.Length);
tmpStr += lowerChars[iRandNum];
}
for (int i = 0; i < specCharLength; i++)
{
iRandNum = rnd.Next(specialCahrs.Length);
tmpStr += specialCahrs[iRandNum];
}
//将取得的字符串随机打乱
for (int i = 0; i < length; i++)
{
int n = rnd.Next(tmpStr.Length);
//去除n随机为0的情况
//n = (n == 0) ? 1 : n;
rndStr += tmpStr[n];
tmpStr = tmpStr.Remove(n, 1);
}
tmpStr = rndStr;
}
//默认将返回数字类型的密码
else
{
for (int i = 0; i < length; i++)
{
iRandNum = rnd.Next(numnberChars.Length);
tmpStr += numnberChars[iRandNum];
}
}
return tmpStr;
}
///
/// 获取vm的当前状态(非电源状态)
///
public string GetOperationStatus()
{
string url = string.Format("https://management.core.windows.net/{0}/operations/{1}",
subscriptionID,
requestId);
var result = new MgmtHelper().Request(
out requestId,
url,
null,
"2012-03-01",
null,
"",
"GET");
return result;
}
}
MgmtHelper.cs :
internal class MgmtHelper
{
private static X509Certificate2 GetX509Certificate(string certThumb)
{
X509Certificate2 certificate2 = null;
var store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly);
var fcollection = store.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
store.Close();
if (fcollection.Count > 0)
{
var enu = fcollection.GetEnumerator();
while (enu.MoveNext())
{
var variable = enu.Current;
if ((variable != null && variable.Thumbprint != null) && variable.Thumbprint.Equals(certThumb, StringComparison.InvariantCultureIgnoreCase))
{
certificate2 = variable;
break;
}
}
}
return certificate2;
}
///
/// 直接入读取c根目录的证书
///
///
private static X509Certificate2 GetX509Certificate()
{
return new X509Certificate2("C:\\EDoc2AzureTest.cer", "123456");
}
internal string Request(out string requestId, string url, string contentType, string xmsversion, string config, string certThumb, string method = "POST")
{
var myReq = (HttpWebRequest)WebRequest.Create(
url);
myReq.Method = method;
myReq.Headers.Add("x-ms-version", xmsversion);//"2012-03-01"
myReq.Proxy = null;
myReq.Timeout = 30 * 1000;//30秒
if (!string.IsNullOrEmpty(contentType))
{
myReq.ContentType = contentType;
}
else
{
myReq.ContentLength = 0;
}
if (!string.IsNullOrEmpty(config))
{
string postData = config;
using (Stream reqStream = myReq.GetRequestStream())
{
using (var sw = new System.IO.StreamWriter(reqStream))
{
sw.Write(postData);
sw.Flush();
}
}
}
//myReq.ClientCertificates.Add(GetX509Certificate(certThumb));
myReq.ClientCertificates.Add(GetX509Certificate());
try
{
var myRes = (HttpWebResponse)myReq.GetResponse();
var code = myRes.StatusCode;
requestId = myRes.Headers["x-ms-request-id"];
using (var sr = new StreamReader(myRes.GetResponseStream()))
{
var result = sr.ReadToEnd();
if (string.IsNullOrEmpty(result) == false)
return result;
else return string.Format("{0} ", code);
}
}
catch (WebException exWeb)
{
Stream responseStream = exWeb.Response.GetResponseStream();
var reader = new StreamReader(responseStream);
var xDocResp = new XmlDocument();
xDocResp.Load(reader);
var responseStatus = (HttpWebResponse)exWeb.Response;
if (responseStream != null) responseStream.Close();
reader.Close();
var result = NiceFormatXml(xDocResp);
requestId = "";
return result;
}
}
private string NiceFormatXml(XmlDocument xDoc)
{
var niceString = new StringBuilder();
var strWriter = new StringWriter(niceString);
var xmlWriter = new XmlTextWriter(strWriter);
xmlWriter.Formatting = Formatting.Indented;
xDoc.WriteTo(xmlWriter);
xmlWriter.Close();
strWriter.Close();
return niceString.ToString();
}
}
CreateCS.xml:
<CreateHostedService xmlns="http://schemas.microsoft.com/windowsazure">
<ServiceName>{CSName}ServiceName>
<Label>{LABEL}Label>
<Location>East AsiaLocation>
CreateHostedService>
CreateFromImage.xml:
<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>{EDoc2Dep}Name>
<DeploymentSlot>ProductionDeploymentSlot>
<Label>labelofdepdLabel>
<RoleList>
<Role>
<RoleName>{EDoc2Role}RoleName>
<RoleType>PersistentVMRoleRoleType>
<ConfigurationSets>
<ConfigurationSet>
<ConfigurationSetType>WindowsProvisioningConfigurationConfigurationSetType>
<ComputerName>{EDoc2ComputerName}ComputerName>
<AdminPassword>{EdocPswd}AdminPassword>
<EnableAutomaticUpdates>falseEnableAutomaticUpdates>
ConfigurationSet>
<ConfigurationSet>
<ConfigurationSetType>NetworkConfigurationConfigurationSetType>
<InputEndpoints>
<InputEndpoint>
<LocalPort>3389LocalPort>
<Name>RDPName>
<Port>38983Port>
<Protocol>tcpProtocol>
InputEndpoint>
<InputEndpoint>
<LocalPort>80LocalPort>
<Name>WEBName>
<Port>80Port>
<Protocol>tcpProtocol>
InputEndpoint>
InputEndpoints>
ConfigurationSet>
ConfigurationSets>
<AvailabilitySetName>AvailabilitySetName>
<OSVirtualHardDisk>
<HostCaching>ReadWriteHostCaching>
<DiskName>{EDoc2Disk}DiskName>
<MediaLink>http://{STORAGE}.blob.core.windows.net/vhds/bjer5mun.{EDoc2Medialink}.vhdMediaLink>
<SourceImageName>img14SourceImageName>
OSVirtualHardDisk>
<RoleSize>MediumRoleSize>
Role>
RoleList>
Deployment>
Edoc2Cloud.xml :
<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>nameofcode5Name>
<DeploymentSlot>ProductionDeploymentSlot>
<Label>labelofdepaLabel>
<RoleList>
<Role>
<RoleName>rolecode5RoleName>
<RoleType>PersistentVMRoleRoleType>
<ConfigurationSets>
<ConfigurationSet>
<ConfigurationSetType>WindowsProvisioningConfigurationConfigurationSetType>
<ComputerName>Edoc2ComputerName>
<AdminPassword>Edoc21234AdminPassword>
<EnableAutomaticUpdates>falseEnableAutomaticUpdates>
ConfigurationSet>
<ConfigurationSet>
<ConfigurationSetType>NetworkConfigurationConfigurationSetType>
<InputEndpoints>
<InputEndpoint>
<LocalPort>3389LocalPort>
<Name>RDPName>
<Port>38983Port>
<Protocol>tcpProtocol>
InputEndpoint>
<InputEndpoint>
<LocalPort>80LocalPort>
<Name>webName>
<Port>80Port>
<Protocol>tcpProtocol>
InputEndpoint>
InputEndpoints>
ConfigurationSet>
ConfigurationSets>
<AvailabilitySetName>AvailabilitySetName>
<OSVirtualHardDisk>
<HostCaching>ReadWriteHostCaching>
<DiskName>diskcode5DiskName>
<MediaLink>https://{STORAGE}.blob.core.windows.net/vhds/testBTSa.vhdMediaLink>
<SourceImageName>2cdc6229df6344129ee553dd3499f0d3__BizTalk-Server-2013-StandardSourceImageName>
OSVirtualHardDisk>
<RoleSize>MediumRoleSize>
Role>
RoleList>
Deployment>
Shutdown.xml :
<ShutdownRoleOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<OperationType>ShutdownRoleOperationOperationType>
ShutdownRoleOperation>
StartRole.xml :
<StartRoleOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<OperationType>StartRoleOperationOperationType>
StartRoleOperation>