Project

General

Profile

root / trunk / src / haizea / common / opennebula_xmlrpc.py @ 685

1
import xmlrpclib
2
import os
3
import os.path
4
import hashlib
5

    
6
try:
7
    import xml.etree.ElementTree as ET
8
except ImportError:
9
    # Compatibility with Python <=2.4
10
    import elementtree.ElementTree as ET 
11

    
12
class OpenNebulaXMLRPCClient(object):
13
    
14
    DEFAULT_ONE_AUTH = "~/.one/one_auth"
15
    
16
    def __init__(self, host, port, user, password):
17
        uri = "http://%s:%i" % (host, port)
18
        self.rpc = xmlrpclib.ServerProxy(uri)
19
        try:
20
            methods = self.rpc.system.listMethods()
21
        except xmlrpclib.Fault, err:
22
            raise Exception("Cannot connect to ONE XML RPC server at %s" % uri)        
23
        
24
        if not set(["one.hostpool.info", 
25
                    "one.host.info",
26
                    "one.vmpool.info", 
27
                    "one.vm.info"]).issubset(set(methods)):
28
            raise Exception("XML RPC server does not support required methods. OpenNebula 1.4 or higher is required.")
29
    
30
        passhash = hashlib.sha1(password).hexdigest()
31
        
32
        self.auth = "%s:%s" % (user, passhash)
33
        
34
    @staticmethod
35
    def get_userpass_from_env():
36
        if not os.environ.has_key("ONE_AUTH"):
37
            one_auth = OpenNebulaXMLRPCClient.DEFAULT_ONE_AUTH
38
        else:
39
            one_auth = os.environ["ONE_AUTH"]
40
            
41
        one_auth = os.path.expanduser(one_auth)
42
        
43
        if not os.path.exists(one_auth):
44
            raise Exception("Authorization file %s does not exists" % one_auth) 
45
        
46
        f = open(one_auth, "r")
47
        try:
48
            line = f.readline().strip()
49
            user, passw = line.split(":")
50
            return user, passw
51
        except:
52
            raise Exception("Authorization file is malformed")
53

    
54
        
55
    def hostpool_info(self):
56
        try:
57
            (rc, value) = self.rpc.one.hostpool.info(self.auth)
58
            if rc == False:
59
                raise Exception("ONE reported an error: %s" % value)
60
            else:
61
                hosts = OpenNebulaHost.from_hostpool_xml(value)
62
                return hosts
63
        except xmlrpclib.Fault, err:
64
            raise Exception("XMLRPC fault: %s" % err.faultString)
65
        
66
    def host_info(self, hid):
67
        try:
68
            (rc, value) = self.rpc.one.host.info(self.auth, hid)
69
            if rc == False:
70
                raise Exception("ONE reported an error: %s" % value)
71
            else:
72
                host = OpenNebulaHost.from_host_xml(value)
73
                return host
74
        except xmlrpclib.Fault, err:
75
            raise Exception("XMLRPC fault: %s" % err.faultString)     
76
        
77
    def vmpool_info(self):
78
        try:
79
            (rc, value) = self.rpc.one.vmpool.info(self.auth, -2) # -2: Get all VMs
80
            if rc == False:
81
                raise Exception("ONE reported an error: %s" % value)
82
            else:
83
                hosts = OpenNebulaVM.from_vmpool_xml(value)
84
                return hosts
85
        except xmlrpclib.Fault, err:
86
            raise Exception("XMLRPC fault: %s" % err.faultString)
87
        
88
    def vm_info(self, id):
89
        try:
90
            (rc, value) = self.rpc.one.vm.info(self.auth, id)
91
            if rc == False:
92
                raise Exception("ONE reported an error: %s" % value)
93
            else:
94
                host = OpenNebulaVM.from_vm_xml(value)
95
                return host
96
        except xmlrpclib.Fault, err:
97
            raise Exception("XMLRPC fault: %s" % err.faultString)     
98
        
99
    def vm_deploy(self, vid, hid):
100
        try:
101
            rv = self.rpc.one.vm.deploy(self.auth, vid, hid)
102
            if rv[0] == False:
103
                raise Exception("ONE reported an error: %s" % rv[1])
104
            else:
105
                return
106
        except xmlrpclib.Fault, err:
107
            raise Exception("XMLRPC fault: %s" % err.faultString)                    
108

    
109
    def vm_action(self, action, vid):
110
        if not action in ["shutdown", "hold", "release", "stop", 
111
                          "cancel", "suspend", "resume", "restart", 
112
                          "finalize" ]:
113
            raise Exception("%s is not a valid action" % action)
114
        try:
115
            rv = self.rpc.one.vm.action(self.auth, action, vid)
116
            if rv[0] == False:
117
                raise Exception("ONE reported an error: %s" % rv[1])
118
            else:
119
                return
120
        except xmlrpclib.Fault, err:
121
            raise Exception("XMLRPC fault: %s" % err.faultString)  
122
        
123
    def vm_shutdown(self, vid):
124
        return self.vm_action("shutdown", vid)                  
125

    
126
    def vm_hold(self, vid):
127
        return self.vm_action("hold", vid)                  
128

    
129
    def vm_release(self, vid):
130
        return self.vm_action("release", vid)                  
131

    
132
    def vm_stop(self, vid):
133
        return self.vm_action("stop", vid)                  
134

    
135
    def vm_cancel(self, vid):
136
        return self.vm_action("cancel", vid)                  
137

    
138
    def vm_suspend(self, vid):
139
        return self.vm_action("suspend", vid)                  
140

    
141
    def vm_resume(self, vid):
142
        return self.vm_action("resume", vid)                  
143

    
144
    def vm_restart(self, vid):
145
        return self.vm_action("restart", vid)                  
146

    
147
    def vm_finalize(self, vid):
148
        return self.vm_action("finalize", vid)                  
149

    
150
    
151
class OpenNebulaHost(object):
152

    
153
    STATE_INIT       = 0
154
    STATE_MONITORING = 1
155
    STATE_MONITORED  = 2
156
    STATE_ERROR      = 3
157
    STATE_DISABLED   = 4
158

    
159
    
160
    def __init__(self, host_element):
161
        self.id = int(host_element.find("ID").text)
162
        self.name = host_element.find("NAME").text
163
        self.state = int(host_element.find("STATE").text)
164
        self.im_mad = host_element.find("IM_MAD").text
165
        self.vm_mad = host_element.find("VM_MAD").text
166
        self.tm_mad = host_element.find("TM_MAD").text
167
        self.last_mon_time = int(host_element.find("LAST_MON_TIME").text)
168
        
169
        host_share_element = host_element.find("HOST_SHARE")
170

    
171
        self.disk_usage = int(host_share_element.find("DISK_USAGE").text)
172
        self.mem_usage = int(host_share_element.find("MEM_USAGE").text)
173
        self.cpu_usage = int(host_share_element.find("CPU_USAGE").text)
174
        self.max_disk = int(host_share_element.find("MAX_DISK").text)
175
        self.max_mem = int(host_share_element.find("MAX_MEM").text)
176
        self.max_cpu = int(host_share_element.find("MAX_CPU").text)
177
        self.free_disk = int(host_share_element.find("FREE_DISK").text)
178
        self.free_mem = int(host_share_element.find("FREE_MEM").text)
179
        self.free_cpu = int(host_share_element.find("FREE_CPU").text)
180
        self.used_disk = int(host_share_element.find("USED_DISK").text)
181
        self.used_mem = int(host_share_element.find("USED_MEM").text)
182
        self.used_cpu = int(host_share_element.find("USED_CPU").text)
183
        self.running_vms = int(host_share_element.find("RUNNING_VMS").text)
184
        
185
        self.template = parse_template(host_element.find("TEMPLATE"))
186
           
187

    
188
    @classmethod
189
    def from_host_xml(cls, xmlstr):
190
        host_element = ET.fromstring(xmlstr)
191
        return cls(host_element)
192
    
193
    @classmethod
194
    def from_hostpool_xml(cls, xmlstr):
195
        hostpool_element = ET.fromstring(xmlstr)
196
        host_elements = hostpool_element.findall("HOST")
197
        return [cls(host_element) for host_element in host_elements]
198
    
199
class OpenNebulaVM(object):
200

    
201
    STATE_INIT      = 0
202
    STATE_PENDING   = 1
203
    STATE_HOLD      = 2
204
    STATE_ACTIVE    = 3
205
    STATE_STOPPED   = 4
206
    STATE_SUSPENDED = 5
207
    STATE_DONE      = 6
208
    STATE_FAILED    = 7
209
    
210
    LCMSTATE_LCM_INIT       = 0
211
    LCMSTATE_PROLOG         = 1
212
    LCMSTATE_BOOT           = 2
213
    LCMSTATE_RUNNING        = 3
214
    LCMSTATE_MIGRATE        = 4
215
    LCMSTATE_SAVE_STOP      = 5
216
    LCMSTATE_SAVE_SUSPEND   = 6
217
    LCMSTATE_SAVE_MIGRATE   = 7
218
    LCMSTATE_PROLOG_MIGRATE = 8
219
    LCMSTATE_PROLOG_RESUME  = 9
220
    LCMSTATE_EPILOG_STOP    = 10
221
    LCMSTATE_EPILOG         = 11
222
    LCMSTATE_SHUTDOWN       = 12
223
    LCMSTATE_CANCEL         = 13
224
    LCMSTATE_FAILURE        = 14
225
    LCMSTATE_DELETE         = 15
226
    LCMSTATE_UNKNOWN        = 16
227
    
228

    
229
    def __init__(self, vm_element):
230
        self.id = int(vm_element.find("ID").text)
231
        self.uid = int(vm_element.find("UID").text)
232
        username_element = vm_element.find("USERNAME")
233
        if username_element == None:
234
            self.username = None
235
        else:
236
            self.username = username_element.text   
237
        self.name = vm_element.find("NAME").text
238
        self.last_poll = int(vm_element.find("LAST_POLL").text)
239
        self.state = int(vm_element.find("STATE").text)
240
        self.lcm_state = int(vm_element.find("LCM_STATE").text)
241
        self.stime = int(vm_element.find("STIME").text)
242
        self.etime = int(vm_element.find("ETIME").text)
243
        deploy_id = vm_element.find("DEPLOY_ID").text
244
        if deploy_id == None:
245
            self.deploy_id = None
246
        else:
247
            self.deploy_id = deploy_id
248
        self.memory = int(vm_element.find("MEMORY").text)
249
        self.cpu = int(vm_element.find("CPU").text)
250
        self.net_tx = int(vm_element.find("NET_TX").text)
251
        self.net_rx = int(vm_element.find("NET_RX").text)
252

    
253
        self.template = parse_template(vm_element.find("TEMPLATE"))
254

    
255
    
256
    @classmethod
257
    def from_vm_xml(cls, xmlstr):
258
        vm_element = ET.fromstring(xmlstr)
259
        return cls(vm_element)
260
    
261
    @classmethod
262
    def from_vmpool_xml(cls, xmlstr):
263
        vmpool_element = ET.fromstring(xmlstr)
264
        vm_elements = vmpool_element.findall("VM")
265
        return [cls(vm_element) for vm_element in vm_elements]
266
    
267
def parse_template(template_element):
268
    template = {}
269
    if template_element != None:
270
        for subelement in template_element:
271
            name = subelement.tag
272
            if len(subelement) == 0:
273
                template[name] = subelement.text
274
            else:
275
                template[name] = {}
276
                for subsubelement in subelement:
277
                    template[name][subsubelement.tag] = subsubelement.text
278
                    
279
    return template
280