~ubuntu-branches/ubuntu/natty/nova/natty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short, Chuck Short, Soren Hansen, Thierry Carrez
  • Date: 2011-02-18 09:36:22 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20110218093622-w13dzywbd7vq2qh7
Tags: 2011.2~bzr700-0ubuntu1
[ Chuck Short ]
* New upstream version.

[ Soren Hansen ]
* Rely on --logdir to find and use the correct logfile.
* Remove the postrotate magic for all but nova-objectstore. It is not
  needed anymore due to using RotatingFileHandler for logging.

[ Thierry Carrez ]
* Ship adminclient in a separate package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
# Copyright (c) 2011 Citrix Systems, Inc.
 
4
# Copyright 2011 OpenStack LLC.
 
5
# Copyright 2011 United States Government as represented by the
 
6
# Administrator of the National Aeronautics and Space Administration.
 
7
# All Rights Reserved.
 
8
#
 
9
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
10
#    not use this file except in compliance with the License. You may obtain
 
11
#    a copy of the License at
 
12
#
 
13
#         http://www.apache.org/licenses/LICENSE-2.0
 
14
#
 
15
#    Unless required by applicable law or agreed to in writing, software
 
16
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
17
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
18
#    License for the specific language governing permissions and limitations
 
19
#    under the License.
 
20
 
 
21
#
 
22
# XenAPI plugin for reading/writing information to xenstore
 
23
#
 
24
 
 
25
try:
 
26
    import json
 
27
except ImportError:
 
28
    import simplejson as json
 
29
import os
 
30
import random
 
31
import subprocess
 
32
import tempfile
 
33
import time
 
34
 
 
35
import XenAPIPlugin
 
36
 
 
37
from pluginlib_nova import *
 
38
configure_logging("xenstore")
 
39
import xenstore
 
40
 
 
41
AGENT_TIMEOUT = 30
 
42
 
 
43
 
 
44
def jsonify(fnc):
 
45
    def wrapper(*args, **kwargs):
 
46
        return json.dumps(fnc(*args, **kwargs))
 
47
    return wrapper
 
48
 
 
49
 
 
50
class TimeoutError(StandardError):
 
51
    pass
 
52
 
 
53
 
 
54
@jsonify
 
55
def key_init(self, arg_dict):
 
56
    """Handles the Diffie-Hellman key exchange with the agent to
 
57
    establish the shared secret key used to encrypt/decrypt sensitive
 
58
    info to be passed, such as passwords. Returns the shared
 
59
    secret key value.
 
60
    """
 
61
    pub = int(arg_dict["pub"])
 
62
    arg_dict["value"] = json.dumps({"name": "keyinit", "value": pub})
 
63
    request_id = arg_dict["id"]
 
64
    arg_dict["path"] = "data/host/%s" % request_id
 
65
    xenstore.write_record(self, arg_dict)
 
66
    try:
 
67
        resp = _wait_for_agent(self, request_id, arg_dict)
 
68
    except TimeoutError, e:
 
69
        raise PluginError("%s" % e)
 
70
    return resp
 
71
 
 
72
 
 
73
@jsonify
 
74
def password(self, arg_dict):
 
75
    """Writes a request to xenstore that tells the agent to set
 
76
    the root password for the given VM. The password should be
 
77
    encrypted using the shared secret key that was returned by a
 
78
    previous call to key_init. The encrypted password value should
 
79
    be passed as the value for the 'enc_pass' key in arg_dict.
 
80
    """
 
81
    pub = int(arg_dict["pub"])
 
82
    enc_pass = arg_dict["enc_pass"]
 
83
    arg_dict["value"] = json.dumps({"name": "password", "value": enc_pass})
 
84
    request_id = arg_dict["id"]
 
85
    arg_dict["path"] = "data/host/%s" % request_id
 
86
    xenstore.write_record(self, arg_dict)
 
87
    try:
 
88
        resp = _wait_for_agent(self, request_id, arg_dict)
 
89
    except TimeoutError, e:
 
90
        raise PluginError("%s" % e)
 
91
    return resp
 
92
 
 
93
 
 
94
@jsonify
 
95
def resetnetwork(self, arg_dict):
 
96
    """Writes a resquest to xenstore that tells the agent
 
97
    to reset networking.
 
98
    """
 
99
    arg_dict['value'] = json.dumps({'name': 'resetnetwork', 'value': ''})
 
100
    request_id = arg_dict['id']
 
101
    arg_dict['path'] = "data/host/%s" % request_id
 
102
    xenstore.write_record(self, arg_dict)
 
103
 
 
104
 
 
105
def _wait_for_agent(self, request_id, arg_dict):
 
106
    """Periodically checks xenstore for a response from the agent.
 
107
    The request is always written to 'data/host/{id}', and
 
108
    the agent's response for that request will be in 'data/guest/{id}'.
 
109
    If no value appears from the agent within the time specified by
 
110
    AGENT_TIMEOUT, the original request is deleted and a TimeoutError
 
111
    is returned.
 
112
    """
 
113
    arg_dict["path"] = "data/guest/%s" % request_id
 
114
    arg_dict["ignore_missing_path"] = True
 
115
    start = time.time()
 
116
    while True:
 
117
        if time.time() - start > AGENT_TIMEOUT:
 
118
            # No response within the timeout period; bail out
 
119
            # First, delete the request record
 
120
            arg_dict["path"] = "data/host/%s" % request_id
 
121
            xenstore.delete_record(self, arg_dict)
 
122
            raise TimeoutError(
 
123
                    "TIMEOUT: No response from agent within %s seconds." %
 
124
                    AGENT_TIMEOUT)
 
125
        ret = xenstore.read_record(self, arg_dict)
 
126
        # Note: the response for None with be a string that includes
 
127
        # double quotes.
 
128
        if ret != '"None"':
 
129
            # The agent responded
 
130
            return ret
 
131
        else:
 
132
            time.sleep(3)
 
133
 
 
134
 
 
135
if __name__ == "__main__":
 
136
    XenAPIPlugin.dispatch(
 
137
        {"key_init": key_init,
 
138
        "password": password,
 
139
        "resetnetwork": resetnetwork})