hl10502的博客

XenCenter分析(二)

要使用XenCenter来管理XenServer主机和资源池,以及部署、监视、管理和迁移虚拟机。

首先需要添加XenServer物理主机。

XenCenter添加服务器

AddServerDialog

添加服务器的代码在AddServerDialog.cs中。

添加服务器的对话框“添加”按钮的事件AddButton_Click,调用ConnectToServer方法连接服务器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public virtual void AddButton_Click(object sender, EventArgs e)
{
/**
*ip地址与端口,可以一次连接多个主机,以";"分隔
*一般我们连接一个,直接使用ip,端口默认使用80
*/
string hostnameAndPort = ServerNameComboBox.Text.Trim();
//用户名
string username = UsernameTextBox.Text.Trim();
//密码
string password = PasswordTextBox.Text;
//多主机
string[] multipleHosts;
if (TryGetMultipleHosts(hostnameAndPort, out multipleHosts))
{
//循环依次连接
foreach (string h in multipleHosts)
{
ConnectToServer(null, h, ConnectionsManager.DEFAULT_XEN_PORT, username, password, comboBoxClouds.SelectedItem != null ? comboBoxClouds.SelectedItem.ToString() : string.Empty);
}
}
else
{
string hostname;
int port;
if (!StringUtility.TryParseHostname(hostnameAndPort, ConnectionsManager.DEFAULT_XEN_PORT, out hostname, out port))
{
//分隔ip与端口
hostname = hostnameAndPort;
port = ConnectionsManager.DEFAULT_XEN_PORT;
}
//连接主机
ConnectToServer(connection, hostname, port, username, password, comboBoxClouds.SelectedItem != null ? comboBoxClouds.SelectedItem.ToString() : string.Empty);
}
Close();
}

ConnectToServer方法,经ip、用户名、密码等参数组装XenConnection对象,调用XenConnectionUI的BeginConnect方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected void ConnectToServer(IXenConnection conn, string hostname, int port, string username, string password, string version)
{
if (conn == null)
{
XenConnection connection = new XenConnection();
connection.CachePopulated += conn_CachePopulated;
connection.fromDialog = true;
conn = connection;
}
else if (!_changedPass)
{
conn.EndConnect(); // in case we're already connected
}
conn.Hostname = hostname;
conn.Port = port;
conn.Username = username;
conn.Password = password;
conn.ExpectPasswordIsCorrect = false;
conn.Version = version;
if (!_changedPass)
XenConnectionUI.BeginConnect(conn, true, Owner, false);
}

XenConnectionUI的BeginConnect方法,调用XenConnection的BeginConnect方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void BeginConnect(IXenConnection connection, bool interactive, Form owner, bool initiateMasterSearch)
{
Program.AssertOnEventThread();
//注册连接事件,连接结果与连接状态的处理
RegisterEventHandlers(connection);
if (interactive)
{
// CA-214953 - Focus on this connection's dialog, if one exists, otherwise create one
ConnectingToServerDialog dlg;
if (connectionDialogs.TryGetValue(connection, out dlg))
{
UnregisterEventHandlers(connection);
if (dlg.WindowState == FormWindowState.Minimized)
dlg.WindowState = FormWindowState.Normal;
dlg.Focus();
return;
}
dlg = new ConnectingToServerDialog(connection);
connectionDialogs.Add(connection, dlg);
dlg.BeginConnect(owner, initiateMasterSearch);
}
else
((XenConnection)connection).BeginConnect(initiateMasterSearch, PromptForNewPassword);
}

XenConnection的BeginConnect方法,开启新线程处理连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//清除事件队列
ClearEventQueue();
OnBeforeMajorChange(false);
Cache.Clear();
OnAfterMajorChange(false);
//设置连接任务对象
connectTask = new ConnectTask(Hostname, Port);
StopMonitor();
heartbeat = new Heartbeat(this, XenAdminConfigManager.Provider.ConnectionTimeout);
//开启连接工作线程
Thread t = new Thread(ConnectWorkerThread);
t.Name = "Connection to " + Hostname;
t.IsBackground = true;
t.Start(connectTask);

ConnectWorkerThread线程,调用NewSession方法创建连接的会话。

1
2
3
4
5
6
7
8
9
10
11
12
13
private void ConnectWorkerThread(object o)
{
ConnectTask task = (ConnectTask)o;
Exception error = null;
Pool pool = null;
try
{
log.DebugFormat("IXenConnection: trying to connect to {0}", HostnameWithPort);
//创建连接会话
Session session = NewSession(task.Hostname, task.Port, Username, Password, false);
// Save the session so we can log it out later
task.Session = session;

NewSession方法调用GetNewSession方法

1
2
3
4
5
6
7
private Session NewSession(string hostname, int port, string username, string password, bool isElevated)
{
Password = password;
Username = username;
return GetNewSession(hostname, port, username, password, isElevated);
}

GetNewSession方法,创建会话之后,使用用户名密码登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Session GetNewSession(string hostname, int port, string username, string password, bool isElevated)
{
const int DELAY = 250; // unit = ms
int attempt = 0;
while (true)
{
attempt++;
string uname = isElevated ? username : Username;
string pwd = isElevated ? password : Password; // Keep the password that we're using for this iteration, as it may
// be changed by another thread handling an authentication failure.
// For elevated session we use the elevated username and password passed into this function,
// as the connection's Username and Password are not updated.
//创建会话
Session session = SessionFactory.CreateSession(this, hostname, port);
if (isElevated)
session.IsElevatedSession = true;
try
{
//使用用户名、密码登录
session.login_with_password(uname, pwd, !string.IsNullOrEmpty(Version) ? Version : Helper.APIVersionString(API_Version.LATEST), Session.UserAgent);
return session;
}