Project

General

Profile

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

1
import xmlrpclib
2
import os
3
import hashlib
4
import xml.etree.ElementTree as ET
5

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

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

    
105
    def vm_hold(self, vid):
106
        return self.vm_action("hold", vid)                  
107

    
108
    def vm_release(self, vid):
109
        return self.vm_action("release", vid)                  
110

    
111
    def vm_stop(self, vid):
112
        return self.vm_action("stop", vid)                  
113

    
114
    def vm_cancel(self, vid):
115
        return self.vm_action("cancel", vid)                  
116

    
117
    def vm_suspend(self, vid):
118
        return self.vm_action("suspend", vid)                  
119

    
120
    def vm_resume(self, vid):
121
        return self.vm_action("resume", vid)                  
122

    
123
    def vm_restart(self, vid):
124
        return self.vm_action("restart", vid)                  
125

    
126
    def vm_finalize(self, vid):
127
        return self.vm_action("finalize", vid)                  
128

    
129
    
130
class OpenNebulaHost(object):
131

    
132
    STATE_INIT       = 0
133
    STATE_MONITORING = 1
134
    STATE_MONITORED  = 2
135
    STATE_ERROR      = 3
136
    STATE_DISABLED   = 4
137

    
138
    
139
    def __init__(self, host_element):
140
        self.id = int(host_element.find("ID").text)
141
        self.name = host_element.find("NAME").text
142
        self.state = int(host_element.find("STATE").text)
143
        self.im_mad = host_element.find("IM_MAD").text
144
        self.vm_mad = host_element.find("VM_MAD").text
145
        self.tm_mad = host_element.find("TM_MAD").text
146
        self.last_mon_time = int(host_element.find("LAST_MON_TIME").text)
147
        
148
        host_share_element = host_element.find("HOST_SHARE")
149

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

    
167
    @classmethod
168
    def from_host_xml(cls, xmlstr):
169
        host_element = ET.fromstring(xmlstr)
170
        return cls(host_element)
171
    
172
    @classmethod
173
    def from_hostpool_xml(cls, xmlstr):
174
        hostpool_element = ET.fromstring(xmlstr)
175
        host_elements = hostpool_element.findall("HOST")
176
        return [cls(host_element) for host_element in host_elements]
177
    
178
class OpenNebulaVM(object):
179

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

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

    
232
        self.template = parse_template(vm_element.find("TEMPLATE"))
233

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