~rackspace-titan/nova/osapi-ipv6-lp798457

« back to all changes in this revision

Viewing changes to plugins/xenserver/xenapi/etc/xapi.d/plugins/agent

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.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
import XenAPIPlugin
38
38
 
39
39
from pluginlib_nova import *
40
 
configure_logging("xenstore")
 
40
configure_logging("agent")
41
41
import xenstore
42
42
 
43
43
AGENT_TIMEOUT = 30
114
114
    xenstore.write_record(self, arg_dict)
115
115
 
116
116
 
117
 
@jsonify
118
117
def inject_file(self, arg_dict):
119
118
    """Expects a file path and the contents of the file to be written. Both
120
119
    should be base64-encoded in order to eliminate errors as they are passed
129
128
    b64_path = arg_dict["b64_path"]
130
129
    b64_file = arg_dict["b64_contents"]
131
130
    request_id = arg_dict["id"]
132
 
    if self._agent_has_method("file_inject"):
 
131
    agent_features = _get_agent_features(self, arg_dict)
 
132
    if "file_inject" in agent_features:
133
133
        # New version of the agent.  Agent should receive a 'value'
134
134
        # key whose value is a dictionary containing 'b64_path' and
135
135
        # 'b64_file'.  See old version below.
136
136
        arg_dict["value"] = json.dumps({"name": "file_inject",
137
137
                "value": {"b64_path": b64_path, "b64_file": b64_file}})
138
 
    elif self._agent_has_method("injectfile"):
 
138
    elif "injectfile" in agent_features:
139
139
        # Old agent requires file path and file contents to be
140
140
        # combined into one base64 value.
141
141
        raw_path = base64.b64decode(b64_path)
142
142
        raw_file = base64.b64decode(b64_file)
143
 
        new_b64 = base64.b64encode("%s,%s") % (raw_path, raw_file)
 
143
        new_b64 = base64.b64encode("%s,%s" % (raw_path, raw_file))
144
144
        arg_dict["value"] = json.dumps({"name": "injectfile",
145
145
                "value": new_b64})
146
146
    else:
174
174
    return resp
175
175
 
176
176
 
177
 
def _agent_has_method(self, method):
178
 
    """Check that the agent has a particular method by checking its
179
 
    features.  Cache the features so we don't have to query the agent
180
 
    every time we need to check.
181
 
    """
 
177
def _get_agent_features(self, arg_dict):
 
178
    """Return an array of features that an agent supports."""
 
179
    tmp_id = commands.getoutput("uuidgen")
 
180
    dct = {}
 
181
    dct.update(arg_dict)
 
182
    dct["value"] = json.dumps({"name": "features", "value": ""})
 
183
    dct["path"] = "data/host/%s" % tmp_id
 
184
    xenstore.write_record(self, dct)
182
185
    try:
183
 
        self._agent_methods
184
 
    except AttributeError:
185
 
        self._agent_methods = []
186
 
    if not self._agent_methods:
187
 
        # Haven't been defined
188
 
        tmp_id = commands.getoutput("uuidgen")
189
 
        dct = {}
190
 
        dct["value"] = json.dumps({"name": "features", "value": ""})
191
 
        dct["path"] = "data/host/%s" % tmp_id
192
 
        xenstore.write_record(self, dct)
193
 
        try:
194
 
            resp = _wait_for_agent(self, tmp_id, dct)
195
 
        except TimeoutError, e:
196
 
            raise PluginError(e)
197
 
        response = json.loads(resp)
198
 
        # The agent returns a comma-separated list of methods.
199
 
        self._agent_methods = response.split(",")
200
 
    return method in self._agent_methods
 
186
        resp = _wait_for_agent(self, tmp_id, dct)
 
187
    except TimeoutError, e:
 
188
        raise PluginError(e)
 
189
    response = json.loads(resp)
 
190
    if response['returncode'] != 0:
 
191
        return response["message"].split(",")
 
192
    else:
 
193
        return {}
201
194
 
202
195
 
203
196
def _wait_for_agent(self, request_id, arg_dict):