diff options
author | Dan Prince <dan.prince@rackspace.com> | 2011-07-18 19:07:20 +0000 |
---|---|---|
committer | Tarmac <> | 2011-07-18 19:07:20 +0000 |
commit | d101bb53cf310e1f093c46cdbdbe2c5b0207e49e (patch) | |
tree | be3af18521f98773afb2aa0390d1997a7d26e21a | |
parent | cf25ab33cb7d6b5e233a767ad96b3c45b1387b5e (diff) | |
parent | 813253e8bea9a8db9c1df45f9aa5e094503a015a (diff) | |
download | nova-d101bb53cf310e1f093c46cdbdbe2c5b0207e49e.tar.gz nova-d101bb53cf310e1f093c46cdbdbe2c5b0207e49e.tar.xz nova-d101bb53cf310e1f093c46cdbdbe2c5b0207e49e.zip |
Updates to the XenServer agent plugin to fix file injection:
-Update _agent_has_method so that it parses the features 'message' from nova-agent correctly. (it was trying to call .split on a dict).
-Rip out the agent_has_method caching functionality which just plain wasn't working (with XenServer 5.6 SP2).
-Pass the arg_dict to _agent_has_method. This fixes an issue where a subsequent call to xenstore.write_record didn't get the 'dom_id' (KeyError).
-Fix a string formatting issue in inject_file in creating the b64 data.
-rwxr-xr-x | plugins/xenserver/xenapi/etc/xapi.d/plugins/agent | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent index 68d7e7bff..288ccc78a 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent @@ -37,7 +37,7 @@ import time import XenAPIPlugin from pluginlib_nova import * -configure_logging("xenstore") +configure_logging("agent") import xenstore AGENT_TIMEOUT = 30 @@ -114,7 +114,6 @@ def resetnetwork(self, arg_dict): xenstore.write_record(self, arg_dict) -@jsonify def inject_file(self, arg_dict): """Expects a file path and the contents of the file to be written. Both should be base64-encoded in order to eliminate errors as they are passed @@ -129,18 +128,19 @@ def inject_file(self, arg_dict): b64_path = arg_dict["b64_path"] b64_file = arg_dict["b64_contents"] request_id = arg_dict["id"] - if self._agent_has_method("file_inject"): + agent_features = _get_agent_features(self, arg_dict) + if "file_inject" in agent_features: # New version of the agent. Agent should receive a 'value' # key whose value is a dictionary containing 'b64_path' and # 'b64_file'. See old version below. arg_dict["value"] = json.dumps({"name": "file_inject", "value": {"b64_path": b64_path, "b64_file": b64_file}}) - elif self._agent_has_method("injectfile"): + elif "injectfile" in agent_features: # Old agent requires file path and file contents to be # combined into one base64 value. raw_path = base64.b64decode(b64_path) raw_file = base64.b64decode(b64_file) - new_b64 = base64.b64encode("%s,%s") % (raw_path, raw_file) + new_b64 = base64.b64encode("%s,%s" % (raw_path, raw_file)) arg_dict["value"] = json.dumps({"name": "injectfile", "value": new_b64}) else: @@ -174,30 +174,23 @@ def agent_update(self, arg_dict): return resp -def _agent_has_method(self, method): - """Check that the agent has a particular method by checking its - features. Cache the features so we don't have to query the agent - every time we need to check. - """ +def _get_agent_features(self, arg_dict): + """Return an array of features that an agent supports.""" + tmp_id = commands.getoutput("uuidgen") + dct = {} + dct.update(arg_dict) + dct["value"] = json.dumps({"name": "features", "value": ""}) + dct["path"] = "data/host/%s" % tmp_id + xenstore.write_record(self, dct) try: - self._agent_methods - except AttributeError: - self._agent_methods = [] - if not self._agent_methods: - # Haven't been defined - tmp_id = commands.getoutput("uuidgen") - dct = {} - dct["value"] = json.dumps({"name": "features", "value": ""}) - dct["path"] = "data/host/%s" % tmp_id - xenstore.write_record(self, dct) - try: - resp = _wait_for_agent(self, tmp_id, dct) - except TimeoutError, e: - raise PluginError(e) - response = json.loads(resp) - # The agent returns a comma-separated list of methods. - self._agent_methods = response.split(",") - return method in self._agent_methods + resp = _wait_for_agent(self, tmp_id, dct) + except TimeoutError, e: + raise PluginError(e) + response = json.loads(resp) + if response['returncode'] != 0: + return response["message"].split(",") + else: + return {} def _wait_for_agent(self, request_id, arg_dict): |