mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			374 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			374 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| // Copyright 2012 Citrix Systems, Inc. Licensed under the
 | |
| // Apache License, Version 2.0 (the "License"); you may not use this
 | |
| // file except in compliance with the License.  Citrix Systems, Inc.
 | |
| // reserves all rights not expressly granted by the License.
 | |
| // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| // 
 | |
| // Automatically generated by addcopyright.py at 04/03/2012
 | |
|  * follows:
 | |
|  *   Linking this library statically or dynamically with other modules is
 | |
|  *   making a combined work based on this library. Thus, the terms and
 | |
|  *   permission to link this library with independent modules to produce an
 | |
|  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | |
| package com.xensource.xenapi;
 | |
| 
 | |
| import java.net.URL;
 | |
| import java.util.Map;
 | |
| import java.util.TimeZone;
 | |
| 
 | |
| import org.apache.xmlrpc.XmlRpcException;
 | |
| import org.apache.xmlrpc.client.XmlRpcClient;
 | |
| import org.apache.xmlrpc.client.XmlRpcClientConfig;
 | |
| import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
 | |
| import org.apache.xmlrpc.client.XmlRpcHttpClientConfig;
 | |
| import org.apache.xmlrpc.client.XmlRpcSun15HttpTransportFactory;
 | |
| 
 | |
| import com.xensource.xenapi.Types.BadServerResponse;
 | |
| import com.xensource.xenapi.Types.SessionAuthenticationFailed;
 | |
| import com.xensource.xenapi.Types.XenAPIException;
 | |
| 
 | |
| /**
 | |
|  * Represents a connection to a XenServer. Creating a new instance of this class initialises a new XmlRpcClient that is
 | |
|  * then used by all method calls: each method call in xenapi takes a Connection as a parameter, composes an XMLRPC
 | |
|  * method call, and dispatches it on the Connection's client via the dispatch method.
 | |
|  */
 | |
| public class Connection
 | |
| {
 | |
|     /**
 | |
|      * The version of the bindings that this class belongs to.
 | |
|      */
 | |
|     public static final String BINDINGS_VERSION = "5.6.100-1";
 | |
|     
 | |
|     /**
 | |
|      * true if the connection is to the Rio edition of XenServer. Certain function calls are not allowed.
 | |
|      * 
 | |
|      * @deprecated Use getAPIVersion() instead.
 | |
|      */
 | |
|     @Deprecated
 | |
|     public Boolean rioConnection = false;
 | |
| 
 | |
|     private APIVersion apiVersion;
 | |
|     
 | |
|     protected int _wait = 600;
 | |
| 
 | |
|     /**
 | |
|      * Updated when Session.login_with_password() is called.
 | |
|      */
 | |
|     public APIVersion getAPIVersion()
 | |
|     {
 | |
|         return apiVersion;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * The opaque reference to the session used by this connection
 | |
|      */
 | |
|     private String sessionReference;
 | |
| 
 | |
|     /**
 | |
|      * As seen by the xmlrpc library. From our point of view it's a server.
 | |
|      */
 | |
|     private final XmlRpcClient client;
 | |
| 
 | |
|     private final boolean deprecatedConstructorUsed;
 | |
| 
 | |
|     /**
 | |
|      * Creates a connection to a particular server using a given username and password. This object can then be passed
 | |
|      * in to any other API calls.
 | |
|      * 
 | |
|      * This constructor calls Session.loginWithPassword, passing itself as the first parameter.
 | |
|      * 
 | |
|      * When this constructor is used, a call to dispose() (also called in the Connection's finalizer) will attempt a
 | |
|      * Session.logout on this connection.
 | |
|      * 
 | |
|      * @deprecated Use a constructor that takes a URL as the first parameter instead.
 | |
|      */
 | |
|     @Deprecated
 | |
|     public Connection(String client, String username, String password) throws java.net.MalformedURLException,
 | |
|         XmlRpcException, BadServerResponse, SessionAuthenticationFailed, XenAPIException
 | |
|     {
 | |
|         deprecatedConstructorUsed = true;
 | |
| 
 | |
|         // To login normally we call login_with_password(username, password, "1.X").  On rio this call fails and we
 | |
|         // should use login_with_password(username,password) instead, and note that we are talking to a rio host so that we
 | |
|         // can refuse to make certain miami-specific calls
 | |
|         final String ApiVersion = APIVersion.latest().toString();
 | |
|         this.client = getClientFromURL(new URL(client));
 | |
|         try
 | |
|         {
 | |
|             //first try to login the modern way
 | |
|             this.sessionReference = loginWithPassword(this.client, username, password, ApiVersion);
 | |
|         } catch (BadServerResponse e)
 | |
|         {
 | |
|             //oops, something went wrong
 | |
|             String[] errDesc = e.errorDescription;
 | |
|             //was the problem that the host was running rio? If so it will have complained that it got three parameters
 | |
|             //instead of two. Let us carefully verify the details of this complaint
 | |
|             if (0 == errDesc[0].compareTo("MESSAGE_PARAMETER_COUNT_MISMATCH")
 | |
|                     && 0 == errDesc[1].compareTo("session.login_with_password")
 | |
|                     && 0 == errDesc[2].compareTo("2")
 | |
|                     && 0 == errDesc[3].compareTo("3"))
 | |
|             {
 | |
|                 //and if so, we can have another go, using the older login method, and see how that goes.
 | |
|                 this.sessionReference = loginWithPassword(this.client, username, password);
 | |
|                 //success!. Note that we are talking to an old host on this connection
 | |
|                 this.rioConnection = true;
 | |
|             } else
 | |
|             {
 | |
|                 //Hmm... Can't solve this here. Let upstairs know about the problem.
 | |
|                 throw e;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             setAPIVersion(new Session(sessionReference));
 | |
|         }
 | |
|         catch (XenAPIException exn)
 | |
|         {
 | |
|             dispose();
 | |
|             throw exn;
 | |
|         }
 | |
|         catch (XmlRpcException exn)
 | |
|         {
 | |
|             dispose();
 | |
|             throw exn;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Creates a connection to a particular server using a given username and password. This object can then be passed
 | |
|      * in to any other API calls.
 | |
|      * 
 | |
|      * Note this constructor does NOT call Session.loginWithPassword; the programmer is responsible for calling it,
 | |
|      * passing the Connection as a parameter. No attempt to connect to the server is made until login is called.
 | |
|      * 
 | |
|      * When this constructor is used, a call to dispose() will do nothing. The programmer is responsible for manually
 | |
|      * logging out the Session.
 | |
|      */
 | |
|     public Connection(URL url, int wait)
 | |
|     {
 | |
|         deprecatedConstructorUsed = false;
 | |
|         _wait = wait;
 | |
|         this.client = getClientFromURL(url);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Creates a connection to a particular server using a given username and password. This object can then be passed
 | |
|      * in to any other API calls.
 | |
|      * 
 | |
|      * The additional sessionReference parameter must be a reference to a logged-in Session. Any method calls on this
 | |
|      * Connection will use it. This constructor does not call Session.loginWithPassword, and dispose() on the resulting
 | |
|      * Connection object does not call Session.logout. The programmer is responsible for ensuring the Session is logged
 | |
|      * in and out correctly.
 | |
|      */
 | |
|     public Connection(URL url, String sessionReference)
 | |
|     {
 | |
|         deprecatedConstructorUsed = false;
 | |
| 
 | |
|         this.client = getClientFromURL(url);
 | |
|         this.sessionReference = sessionReference;
 | |
|     }
 | |
| 
 | |
|     protected void finalize() throws Throwable
 | |
|     {
 | |
|         dispose();
 | |
|         super.finalize();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Nothrow guarantee.
 | |
|      */
 | |
|     public void dispose()
 | |
|     {
 | |
|         if (!deprecatedConstructorUsed)
 | |
|         {
 | |
|             // We only need to do the Session.logout if they used the old deprecated constructor.
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             if (sessionReference != null)
 | |
|             {
 | |
|                 String method_call = "session.logout";
 | |
|                 Object[] method_params = { Marshalling.toXMLRPC(this.sessionReference) };
 | |
|                 client.execute(method_call, method_params);
 | |
|                 sessionReference = null;
 | |
|             }
 | |
|         }
 | |
|         catch (XmlRpcException exn)
 | |
|         {
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @deprecated The programmer is now responsible for calling login/logout themselves.
 | |
|      */
 | |
|     @Deprecated
 | |
|     private static String loginWithPassword(XmlRpcClient client, String username, String password)
 | |
|             throws BadServerResponse, XmlRpcException, SessionAuthenticationFailed
 | |
|     {
 | |
|         String method_call = "session.login_with_password";
 | |
|         Object[] method_params = { Marshalling.toXMLRPC(username), Marshalling.toXMLRPC(password) };
 | |
|         Map response = (Map) client.execute(method_call, method_params);
 | |
|         if (response.get("Status").equals("Success"))
 | |
|         {
 | |
|             return (String) response.get("Value");
 | |
|         } else if (response.get("Status").equals("Failure"))
 | |
|         {
 | |
|             Object[] error = (Object[]) response.get("ErrorDescription");
 | |
|             if (error[0].equals("SESSION_AUTHENTICATION_FAILED"))
 | |
|             {
 | |
|                 throw new SessionAuthenticationFailed();
 | |
|             }
 | |
|         }
 | |
|         throw new BadServerResponse(response);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @deprecated The programmer is now responsible for calling login/logout themselves.
 | |
|      */
 | |
|     @Deprecated
 | |
|     private static String loginWithPassword(XmlRpcClient client, String username, String password, String ApiVersion)
 | |
|             throws BadServerResponse, XmlRpcException, SessionAuthenticationFailed
 | |
|     {
 | |
|         String method_call = "session.login_with_password";
 | |
|         Object[] method_params = { Marshalling.toXMLRPC(username), Marshalling.toXMLRPC(password),
 | |
|                 Marshalling.toXMLRPC(ApiVersion) };
 | |
|         Map response = (Map) client.execute(method_call, method_params);
 | |
|         if (response.get("Status").equals("Success"))
 | |
|         {
 | |
|             return (String) response.get("Value");
 | |
|         } else if (response.get("Status").equals("Failure"))
 | |
|         {
 | |
|             Object[] error = (Object[]) response.get("ErrorDescription");
 | |
|             if (error[0].equals("SESSION_AUTHENTICATION_FAILED"))
 | |
|             {
 | |
|                 throw new SessionAuthenticationFailed();
 | |
|             }
 | |
|         }
 | |
|         throw new BadServerResponse(response);
 | |
|     }
 | |
| 
 | |
|     private XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
 | |
| 
 | |
|     public XmlRpcClientConfigImpl getConfig()
 | |
|     {
 | |
| 	return config;
 | |
|     }
 | |
|     protected XmlRpcClient getClientFromURL(URL url)
 | |
|     {
 | |
|         config.setTimeZone(TimeZone.getTimeZone("UTC"));
 | |
|         config.setServerURL(url);
 | |
|         config.setReplyTimeout(_wait * 1000);
 | |
|         config.setConnectionTimeout(5000);
 | |
|         XmlRpcClient client = new XmlRpcClient();
 | |
|         client.setConfig(config);
 | |
|         return client;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Because the binding calls are constructing their own parameter lists, they need to be able to get to 
 | |
|      * the session reference directly. This is all rather ugly and needs redone
 | |
|      * Changed to public to allow easier integration with HTTP-level streaming interface,
 | |
|      * see CA-15447
 | |
|      */
 | |
|     public String getSessionReference()
 | |
|     {
 | |
|         return this.sessionReference;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * The (auto-generated parts of) the bindings dispatch XMLRPC calls on this Connection's client through this method.
 | |
|      */
 | |
|     protected Map dispatch(String method_call, Object[] method_params) throws XmlRpcException, XenAPIException
 | |
|     {
 | |
|         Map response = (Map) client.execute(method_call, method_params);
 | |
| 
 | |
|         if (!deprecatedConstructorUsed)
 | |
|         {
 | |
|             // We are using the new-style constructor which doesn't perform login.
 | |
|             // Set this Connection's Session reference from the value returned on the wire.
 | |
|             if (method_call.equals("session.login_with_password") &&
 | |
|                 response.get("Status").equals("Success"))
 | |
|             {
 | |
|                 // Store the Session reference and ask the server what the
 | |
| 		// API version it's using is.
 | |
|                 Session session = Types.toSession(response.get("Value"));
 | |
| 		sessionReference = session.ref;
 | |
|                 setAPIVersion(session);
 | |
|             }
 | |
|             else if (method_call.equals("session.slave_local_login_with_password") &&
 | |
|                      response.get("Status").equals("Success"))
 | |
|             {
 | |
|                 // Store the Session reference and assume API version 1.2.
 | |
|                 sessionReference = Types.toSession(response.get("Value")).ref;
 | |
|                 apiVersion = APIVersion.API_1_2;
 | |
|             }
 | |
|             else if (method_call.equals("session.logout"))
 | |
|             {
 | |
|                 // Work around a bug in XenServer 5.0 and below.
 | |
|                 // session.login_with_password should have rejected us with
 | |
|                 // HOST_IS_SLAVE, but instead we don't find out until later.
 | |
|                 // We don't want to leak the session, so we need to log out
 | |
|                 // this session from the master instead.
 | |
|                 if (response.get("Status").equals("Failure"))
 | |
|                 {
 | |
|                     Object[] error = (Object[]) response.get("ErrorDescription");
 | |
|                     if (error.length == 2 && error[0].equals("HOST_IS_SLAVE"))
 | |
|                     {
 | |
|                         try
 | |
|                         {
 | |
|                             URL client_url =
 | |
|                                 ((XmlRpcHttpClientConfig)client.getClientConfig()).getServerURL();
 | |
|                             Connection tmp_conn =
 | |
|                                 new Connection(new URL(client_url.getProtocol(),
 | |
|                                                        (String)error[1],
 | |
|                                                        client_url.getPort(),
 | |
|                                                        client_url.getFile()), _wait);
 | |
|                             tmp_conn.sessionReference = sessionReference;
 | |
|                             try
 | |
|                             {
 | |
|                                 Session.logout(tmp_conn);
 | |
|                             }
 | |
|                             finally
 | |
|                             {
 | |
|                                 tmp_conn.dispose();
 | |
|                             }
 | |
|                         }
 | |
|                         catch (Exception exn2)
 | |
|                         {
 | |
|                             // Ignore -- we're going to throw HostIsSlave anyway.
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // Clear the stored Session reference.
 | |
|                 this.sessionReference = null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return Types.checkResponse(response);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     private void setAPIVersion(Session session) throws XenAPIException, XmlRpcException
 | |
|     {
 | |
|         try
 | |
|         {
 | |
|             long major = session.getThisHost(this).getAPIVersionMajor(this);
 | |
|             long minor = session.getThisHost(this).getAPIVersionMinor(this);
 | |
|             apiVersion = APIVersion.fromMajorMinor(major, minor);
 | |
|         }
 | |
|         catch (BadServerResponse exn)
 | |
|         {
 | |
|             apiVersion = APIVersion.API_1_1;
 | |
|         }
 | |
|     }
 | |
| }
 |