Project

General

Profile

root / branches / 1.1 / src / haizea / common / opennebula_xmlrpc.py @ 846

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
    
13
    DEFAULT_ONE_AUTH = "~/.one/one_auth"
14
    
15
    def __init__(self, host, port, user, password):
16
        uri = "http://%s:%i" % (host, port)
17
        self.rpc = xmlrpclib.ServerProxy(uri)
18
        try:
19
            methods = self.rpc.system.listMethods()
20
        except xmlrpclib.Fault, err:
21
            raise Exception("Cannot connect to ONE XML RPC server at %s" % uri)        
22
        
23
        if not set(["one.hostpool.info", 
24
                    "one.host.info",
25
                    "one.vmpool.info", 
26
                    "one.vm.info"]).issubset(set(methods)):
27
            raise Exception("XML RPC server does not support required methods. OpenNebula 1.4 or higher is required.")
28
    
29
        passhash = hashlib.sha1(password).hexdigest()
30
        
31
        self.auth = "%s:%s" % (user, passhash)
32
        
33
    @staticmethod
34
    def get_userpass_from_env():
35
        if not os.environ.has_key("ONE_AUTH"):
36
            one_auth = OpenNebulaXMLRPCClient.DEFAULT_ONE_AUTH
37
        else:
38
            one_auth = os.environ["ONE_AUTH"]
39
            
40
        one_auth = os.path.expanduser(one_auth)
41
        
42
        if not os.path.exists(one_auth):
43
            raise Exception("Authorization file %s does not exists" % one_auth) 
44
        
45
        f = open(one_auth, "r")
46
        try:
47
            line = f.readline().strip()
48
            user, passw = line.split(":")
49
            return user, passw
50
        except:
51
            raise Exception("Authorization file is malformed")
52
        
53
    def hostpool_info(self):
54
        try:
55
            (rc, value) = self.rpc.one.hostpool.info(self.auth)
56
            if rc == False:
57
                raise Exception("ONE reported an error: %s" % value)
58
            else:
59
                hosts = OpenNebulaHost.from_hostpool_xml(value)
60
                return hosts
61
        except xmlrpclib.Fault, err:
62
            raise Exception("XMLRPC fault: %s" % err.faultString)
63
        
64
    def host_info(self, hid):
65
        try:
66
            (rc, value) = self.rpc.one.host.info(self.auth, hid)
67
            if rc == False:
68
                raise Exception("ONE reported an error: %s" % value)
69
            else:
70
                host = OpenNebulaHost.from_host_xml(value)
71
                return host
72
        except xmlrpclib.Fault, err:
73
            raise Exception("XMLRPC fault: %s" % err.faultString)     
74
        
75
    def vmpool_info(self):
76
        try:
77
            (rc, value) = self.rpc.one.vmpool.info(self.auth, -2) # -2: Get all VMs
78
            if rc == False:
79
                raise Exception("ONE reported an error: %s" % value)
80
            else:
81
                hosts = OpenNebulaVM.from_vmpool_xml(value)
82
                return hosts
83
        except xmlrpclib.Fault, err:
84
            raise Exception("XMLRPC fault: %s" % err.faultString)
85
        
86
    def vm_info(self, id):
87
        try:
88
            (rc, value) = self.rpc.one.vm.info(self.auth, id)
89
            if rc == False:
90
                raise Exception("ONE reported an error: %s" % value)
91
            else:
92
                host = OpenNebulaVM.from_vm_xml(value)
93
                return host
94
        except xmlrpclib.Fault, err:
95
            raise Exception("XMLRPC fault: %s" % err.faultString)     
96
        
97
    def vm_deploy(self, vid, hid):
98
        try:
99
            rv = self.rpc.one.vm.deploy(self.auth, vid, hid)
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_action(self, action, vid):
108
        if not action in ["shutdown", "hold", "release", "stop", 
109
                          "cancel", "suspend", "resume", "restart", 
110
                          "finalize" ]:
111
            raise Exception("%s is not a valid action" % action)
112
        try:
113
            rv = self.rpc.one.vm.action(self.auth, action, vid)
114
            if rv[0] == False:
115
                raise Exception("ONE reported an error: %s" % rv[1])
116
            else:
117
                return
118
        except xmlrpclib.Fault, err:
119
            raise Exception("XMLRPC fault: %s" % err.faultString)  
120
        
121
    def vm_shutdown(self, vid):
122
        return self.vm_action("shutdown", vid)                  
123

    
124
    def vm_hold(self, vid):
125
        return self.vm_action("hold", vid)                  
126

    
127
    def vm_release(self, vid):
128
        return self.vm_action("release", vid)                  
129

    
130
    def vm_stop(self, vid):
131
        return self.vm_action("stop", vid)                  
132

    
133
    def vm_cancel(self, vid):
134
        return self.vm_action("cancel", vid)                  
135

    
136
    def vm_suspend(self, vid):
137
        return self.vm_action("suspend", vid)                  
138

    
139
    def vm_resume(self, vid):
140
        return self.vm_action("resume", vid)                  
141

    
142
    def vm_restart(self, vid):
143
        return self.vm_action("restart", vid)                  
144

    
145
    def vm_finalize(self, vid):
146
        return self.vm_action("finalize", vid)                  
147

    
148
    
149
class OpenNebulaHost(object):
150

    
151
    STATE_INIT       = 0
152
    STATE_MONITORING = 1
153
    STATE_MONITORED  = 2
154
    STATE_ERROR      = 3
155
    STATE_DISABLED   = 4
156

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

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

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

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

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

    
251
        self.template = parse_template(vm_element.find("TEMPLATE"))
252

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