Project

General

Profile

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

1
import xmlrpclib
2
import os
3
import hashlib
4

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

    
11
class OpenNebulaXMLRPCClient(object):
12
    def __init__(self, host, port, user, password):
13
        uri = "http://%s:%i" % (host, port)
14
        self.rpc = xmlrpclib.ServerProxy(uri)
15
        try:
16
            methods = self.rpc.system.listMethods()
17
        except xmlrpclib.Fault, err:
18
            raise Exception("Cannot connect to ONE XML RPC server at %s" % uri)        
19
        
20
        if not set(["one.hostpool.info", 
21
                    "one.host.info",
22
                    "one.vmpool.info", 
23
                    "one.vm.info"]).issubset(set(methods)):
24
            raise Exception("XML RPC server does not support required methods. OpenNebula 1.4 or higher is required.")
25
    
26
        passhash = hashlib.sha1(password).hexdigest()
27
        
28
        self.auth = "%s:%s" % (user, passhash)
29
        
30
    @staticmethod
31
    def get_userpass_from_env():
32
        if not os.environ.has_key("ONE_AUTH"):
33
            return None
34
        else:
35
            auth = os.environ["ONE_AUTH"]
36
            user, passw = auth.split(":")
37
            return user, passw
38
        
39
    def hostpool_info(self):
40
        try:
41
            (rc, value) = self.rpc.one.hostpool.info(self.auth)
42
            if rc == False:
43
                raise Exception("ONE reported an error: %s" % value)
44
            else:
45
                hosts = OpenNebulaHost.from_hostpool_xml(value)
46
                return hosts
47
        except xmlrpclib.Fault, err:
48
            raise Exception("XMLRPC fault: %s" % err.faultString)
49
        
50
    def host_info(self, hid):
51
        try:
52
            (rc, value) = self.rpc.one.host.info(self.auth, hid)
53
            if rc == False:
54
                raise Exception("ONE reported an error: %s" % value)
55
            else:
56
                host = OpenNebulaHost.from_host_xml(value)
57
                return host
58
        except xmlrpclib.Fault, err:
59
            raise Exception("XMLRPC fault: %s" % err.faultString)     
60
        
61
    def vmpool_info(self):
62
        try:
63
            (rc, value) = self.rpc.one.vmpool.info(self.auth, -2) # -2: Get all VMs
64
            if rc == False:
65
                raise Exception("ONE reported an error: %s" % value)
66
            else:
67
                hosts = OpenNebulaVM.from_vmpool_xml(value)
68
                return hosts
69
        except xmlrpclib.Fault, err:
70
            raise Exception("XMLRPC fault: %s" % err.faultString)
71
        
72
    def vm_info(self, id):
73
        try:
74
            (rc, value) = self.rpc.one.vm.info(self.auth, id)
75
            if rc == False:
76
                raise Exception("ONE reported an error: %s" % value)
77
            else:
78
                host = OpenNebulaVM.from_vm_xml(value)
79
                return host
80
        except xmlrpclib.Fault, err:
81
            raise Exception("XMLRPC fault: %s" % err.faultString)     
82
        
83
    def vm_deploy(self, vid, hid):
84
        try:
85
            rv = self.rpc.one.vm.deploy(self.auth, vid, hid)
86
            if rv[0] == False:
87
                raise Exception("ONE reported an error: %s" % rv[1])
88
            else:
89
                return
90
        except xmlrpclib.Fault, err:
91
            raise Exception("XMLRPC fault: %s" % err.faultString)                    
92

    
93
    def vm_action(self, action, vid):
94
        if not action in ["shutdown", "hold", "release", "stop", 
95
                          "cancel", "suspend", "resume", "restart", 
96
                          "finalize" ]:
97
            raise Exception("%s is not a valid action" % action)
98
        try:
99
            rv = self.rpc.one.vm.action(self.auth, action, vid)
100
            if rv[0] == False:
101
                raise Exception("ONE reported an error: %s" % rv[1])
102
            else:
103
                return
104
        except xmlrpclib.Fault, err:
105
            raise Exception("XMLRPC fault: %s" % err.faultString)  
106
        
107
    def vm_shutdown(self, vid):
108
        return self.vm_action("shutdown", vid)                  
109

    
110
    def vm_hold(self, vid):
111
        return self.vm_action("hold", vid)                  
112

    
113
    def vm_release(self, vid):
114
        return self.vm_action("release", vid)                  
115

    
116
    def vm_stop(self, vid):
117
        return self.vm_action("stop", vid)                  
118

    
119
    def vm_cancel(self, vid):
120
        return self.vm_action("cancel", vid)                  
121

    
122
    def vm_suspend(self, vid):
123
        return self.vm_action("suspend", vid)                  
124

    
125
    def vm_resume(self, vid):
126
        return self.vm_action("resume", vid)                  
127

    
128
    def vm_restart(self, vid):
129
        return self.vm_action("restart", vid)                  
130

    
131
    def vm_finalize(self, vid):
132
        return self.vm_action("finalize", vid)                  
133

    
134
    
135
class OpenNebulaHost(object):
136

    
137
    STATE_INIT       = 0
138
    STATE_MONITORING = 1
139
    STATE_MONITORED  = 2
140
    STATE_ERROR      = 3
141
    STATE_DISABLED   = 4
142

    
143
    
144
    def __init__(self, host_element):
145
        self.id = int(host_element.find("ID").text)
146
        self.name = host_element.find("NAME").text
147
        self.state = int(host_element.find("STATE").text)
148
        self.im_mad = host_element.find("IM_MAD").text
149
        self.vm_mad = host_element.find("VM_MAD").text
150
        self.tm_mad = host_element.find("TM_MAD").text
151
        self.last_mon_time = int(host_element.find("LAST_MON_TIME").text)
152
        
153
        host_share_element = host_element.find("HOST_SHARE")
154

    
155
        self.disk_usage = int(host_share_element.find("DISK_USAGE").text)
156
        self.mem_usage = int(host_share_element.find("MEM_USAGE").text)
157
        self.cpu_usage = int(host_share_element.find("CPU_USAGE").text)
158
        self.max_disk = int(host_share_element.find("MAX_DISK").text)
159
        self.max_mem = int(host_share_element.find("MAX_MEM").text)
160
        self.max_cpu = int(host_share_element.find("MAX_CPU").text)
161
        self.free_disk = int(host_share_element.find("FREE_DISK").text)
162
        self.free_mem = int(host_share_element.find("FREE_MEM").text)
163
        self.free_cpu = int(host_share_element.find("FREE_CPU").text)
164
        self.used_disk = int(host_share_element.find("USED_DISK").text)
165
        self.used_mem = int(host_share_element.find("USED_MEM").text)
166
        self.used_cpu = int(host_share_element.find("USED_CPU").text)
167
        self.running_vms = int(host_share_element.find("RUNNING_VMS").text)
168
        
169
        self.template = parse_template(host_element.find("TEMPLATE"))
170
           
171

    
172
    @classmethod
173
    def from_host_xml(cls, xmlstr):
174
        host_element = ET.fromstring(xmlstr)
175
        return cls(host_element)
176
    
177
    @classmethod
178
    def from_hostpool_xml(cls, xmlstr):
179
        hostpool_element = ET.fromstring(xmlstr)
180
        host_elements = hostpool_element.findall("HOST")
181
        return [cls(host_element) for host_element in host_elements]
182
    
183
class OpenNebulaVM(object):
184

    
185
    STATE_INIT      = 0
186
    STATE_PENDING   = 1
187
    STATE_HOLD      = 2
188
    STATE_ACTIVE    = 3
189
    STATE_STOPPED   = 4
190
    STATE_SUSPENDED = 5
191
    STATE_DONE      = 6
192
    STATE_FAILED    = 7
193
    
194
    LCMSTATE_LCM_INIT       = 0
195
    LCMSTATE_PROLOG         = 1
196
    LCMSTATE_BOOT           = 2
197
    LCMSTATE_RUNNING        = 3
198
    LCMSTATE_MIGRATE        = 4
199
    LCMSTATE_SAVE_STOP      = 5
200
    LCMSTATE_SAVE_SUSPEND   = 6
201
    LCMSTATE_SAVE_MIGRATE   = 7
202
    LCMSTATE_PROLOG_MIGRATE = 8
203
    LCMSTATE_PROLOG_RESUME  = 9
204
    LCMSTATE_EPILOG_STOP    = 10
205
    LCMSTATE_EPILOG         = 11
206
    LCMSTATE_SHUTDOWN       = 12
207
    LCMSTATE_CANCEL         = 13
208
    LCMSTATE_FAILURE        = 14
209
    LCMSTATE_DELETE         = 15
210
    LCMSTATE_UNKNOWN        = 16
211
    
212

    
213
    def __init__(self, vm_element):
214
        self.id = int(vm_element.find("ID").text)
215
        self.uid = int(vm_element.find("UID").text)
216
        username_element = vm_element.find("USERNAME")
217
        if username_element == None:
218
            self.username = None
219
        else:
220
            self.username = username_element.text   
221
        self.name = vm_element.find("NAME").text
222
        self.last_poll = int(vm_element.find("LAST_POLL").text)
223
        self.state = int(vm_element.find("STATE").text)
224
        self.lcm_state = int(vm_element.find("LCM_STATE").text)
225
        self.stime = int(vm_element.find("STIME").text)
226
        self.etime = int(vm_element.find("ETIME").text)
227
        deploy_id = vm_element.find("DEPLOY_ID").text
228
        if deploy_id == None:
229
            self.deploy_id = None
230
        else:
231
            self.deploy_id = deploy_id
232
        self.memory = int(vm_element.find("MEMORY").text)
233
        self.cpu = int(vm_element.find("CPU").text)
234
        self.net_tx = int(vm_element.find("NET_TX").text)
235
        self.net_rx = int(vm_element.find("NET_RX").text)
236

    
237
        self.template = parse_template(vm_element.find("TEMPLATE"))
238

    
239
    
240
    @classmethod
241
    def from_vm_xml(cls, xmlstr):
242
        vm_element = ET.fromstring(xmlstr)
243
        return cls(vm_element)
244
    
245
    @classmethod
246
    def from_vmpool_xml(cls, xmlstr):
247
        vmpool_element = ET.fromstring(xmlstr)
248
        vm_elements = vmpool_element.findall("VM")
249
        return [cls(vm_element) for vm_element in vm_elements]
250
    
251
def parse_template(template_element):
252
    template = {}
253
    if template_element != None:
254
        for subelement in template_element:
255
            name = subelement.tag
256
            if len(subelement) == 0:
257
                template[name] = subelement.text
258
            else:
259
                template[name] = {}
260
                for subsubelement in subelement:
261
                    template[name][subsubelement.tag] = subsubelement.text
262
                    
263
    return template
264