Shahar Havivi has uploaded a new change for review.

Change subject: python: support for oVirt API
......................................................................

python: support for oVirt API

Change the connection with oVirt engine to work with oVirt API and not
via direct RESTful calls

Change-Id: I8ab241473b714dacdf57909e02fe1cb579c252e6
Signed-off-by: Shahar Havivi <shav...@redhat.com>
---
A python/OVirtDispatcher.py
M python/README
D python/RestClient.py
D python/RestCommand.py
M python/WebHandler.py
5 files changed, 134 insertions(+), 192 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/samples-portals refs/changes/24/10624/1

diff --git a/python/OVirtDispatcher.py b/python/OVirtDispatcher.py
new file mode 100644
index 0000000..5f26f04
--- /dev/null
+++ b/python/OVirtDispatcher.py
@@ -0,0 +1,60 @@
+from ovirtsdk.api import API
+from ovirtsdk.infrastructure.errors import RequestError, ConnectionError
+
+import ConfigParser
+api = None
+
+class OVirtDispatcher(object):
+
+    def __init__(self):
+        self.config = ConfigParser.ConfigParser()
+        self.config.read('ovirt.conf')
+        self.baseUrl = self.config.get('oVirt', 'BaseUrl')
+
+    def login(self, username, password):
+        global api
+        try:
+            api = API(url=self.baseUrl, username=username, password=password, 
filter=True)
+        except RequestError as reqErr:
+            return False, "Login error"
+        except ConnectionError as conErr:
+            return False, "Bad URL"
+        return True, ''
+
+    def getUserVms(self):
+        global api
+        return api.vms.list()
+
+    def getVmById(self, id):
+        global api
+        return api.vms.get(id)
+
+    def startVm(self, vmid):
+        global api
+        try:
+            api.vms.get(id=vmid).start()
+        except RequestError as reqErr:
+            return False, reqErr.reason, reqErr.detail
+        except ConnectionError as conErr:
+            return False, 'Connection Error'
+        return True, None, None
+
+    def stopVm(self, vmid):
+        global api
+        try:
+            api.vms.get(id=vmid).stop()
+        except RequestError as reqErr:
+            return False, reqErr.reason, reqErr.detail
+        except ConnectionError as conErr:
+            return False, 'Connection Error'
+        return True, None, None
+
+    def ticketVm(self, vmid):
+        global api
+        try:
+            ticket = api.vms.get(id=vmid).ticket()
+            return ticket.get_ticket().get_value(), 
ticket.get_ticket().get_expiry()
+        except RequestError as reqErr:
+            raise Exception(reqErr.reason, reqErr.detail)
+        except ConnectionError as conErr:
+            raise Exception('Connection Error', '')
diff --git a/python/README b/python/README
index 3c9fb13..fb7fa0d 100644
--- a/python/README
+++ b/python/README
@@ -1,3 +1,6 @@
+Install the sdk:
+# yum install ovirt-engine-sdk
+
 This is a Python sample web-portal that uses REST API to view and run VMs from 
oVirt Engine.
 This project run a local web server which can be configure via the ovirt.conf 
file.
 
diff --git a/python/RestClient.py b/python/RestClient.py
deleted file mode 100644
index f7061c3..0000000
--- a/python/RestClient.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import base64
-import httplib
-import urllib2
-import urlparse
-
-cookie = None
-
-'''
-RestClient: handler RESTful post/get methods
-'''
-class RestClient(object):
-
-    def doGetMethod(self, url, userName=None, password=None):
-        global cookie
-        req = urllib2.Request(url)
-        if cookie is None:
-            auth = "%s:%s" % (userName, password)
-            auth = base64.encodestring(auth)
-            req.add_header("Authorization", "Basic %s" % auth)
-        else:
-            req.add_header("Cookie", cookie)
-
-        # run in user level API
-        req.add_header('filter', 'true')
-        # For using REST session via cookies, so we won't have to login on 
every request
-        req.add_header('Prefer', 'persistent-auth')
-        response = urllib2.urlopen(req)
-        if not response.info().getheader('Set-Cookie') is None:
-            cookie = response.info().getheader('Set-Cookie')
-
-        return response.read()
-
-    def doPostMethod(self, url):
-        global cookie
-        u = urlparse.urlparse(url)
-
-        headers = {"Content-type": "application/xml"}
-        headers['filter'] = 'true'
-        headers['Prefer'] = 'persistent-auth'
-        headers['Cookie'] = cookie
-
-        conn = httplib.HTTPConnection(u.hostname, u.port)
-        conn.request("POST", u.path, body="<action/>", headers=headers)
-        res = conn.getresponse()
-        return res.read()
-
-    def resetCookie(self):
-        global cookie
-        cookie = None
diff --git a/python/RestCommand.py b/python/RestCommand.py
deleted file mode 100644
index d161289..0000000
--- a/python/RestCommand.py
+++ /dev/null
@@ -1,97 +0,0 @@
-import RestClient
-
-import ConfigParser
-from xml.dom import minidom
-
-restClient = RestClient.RestClient()
-
-class RestCommand(object):
-
-    def __init__(self):
-        global restClient
-        self.config = ConfigParser.ConfigParser()
-        self.config.read('ovirt.conf')
-        self.baseUrl = self.config.get('oVirt', 'BaseUrl')
-
-    def _parseVm(self, xmlVm):
-        vm = {}
-        vm['startable'] = True
-        vm['stopable'] = True
-        vm['connectable'] = True
-        vm['vmid'] =  xmlVm.getAttribute('id')
-        vm['name'] = 
xmlVm.getElementsByTagName('name').item(0).firstChild.nodeValue
-        vm['status'] = 
xmlVm.getElementsByTagName('status').item(0).getElementsByTagName('state').item(0).firstChild.nodeValue
-        vm['display'] = 
xmlVm.getElementsByTagName('display').item(0).getElementsByTagName('type').item(0).firstChild.nodeValue
-        if len(xmlVm.getElementsByTagName('port')) > 0:
-            vm['port'] = 
xmlVm.getElementsByTagName('port').item(0).firstChild.nodeValue
-        else:
-            vm['port'] = '-1'
-        if len(xmlVm.getElementsByTagName('address')) > 0:
-            vm['address'] = 
xmlVm.getElementsByTagName('address').item(0).firstChild.nodeValue
-        else:
-            vm['address'] = ''
-        return vm
-
-    def login(self, userName, password):
-        self.userName = userName
-        self.password = password
-
-        try:
-            restClient.resetCookie()
-            xml = restClient.doGetMethod(self.baseUrl + '/api', userName, 
password)
-            return True
-        except:
-            return False
-
-    def getUserVms(self):
-        global restClient
-        xml = restClient.doGetMethod(self.baseUrl + '/api/vms')
-        dom = minidom.parseString(xml)
-        xmlVms = dom.getElementsByTagName('vm')
-        vms = []
-        for xmlVm in xmlVms:
-            vms.append(self._parseVm(xmlVm))
-
-        return vms
-
-    def getVmByVmId(self, vmid):
-        global restClient
-        xml = restClient.doGetMethod(self.baseUrl + '/api/vms/' + vmid)
-        dom = minidom.parseString(xml)
-        return self._parseVm(dom.getElementsByTagName('vm')[0])
-
-    '''
-        Method return action results
-
-        input:
-            vmid: guid of vm
-            action: action to run (start, stop or ticket) - there are more 
actions...(never tested)
-
-        return value:
-            dictionary
-            { 'status': 'complete',
-              'reason': '...',    # only if failed
-              'detail': '...',    # only if failed
-              'value': 'XXYYZZ',  # the ticket (password)
-              'expired': '7200',  # in minutes
-            }
-    '''
-    def runAction(self, vmid, action):
-        global restClient
-        ret = {}
-        url = '%s/api/vms/%s/%s' % (self.baseUrl, vmid, action)
-
-        xml = restClient.doPostMethod(url)
-        dom = minidom.parseString(xml)
-
-        ret['status'] = 
dom.getElementsByTagName('state').item(0).firstChild.nodeValue
-        if ret['status'] == 'failed':
-            ret['reason'] = 
dom.getElementsByTagName('reason').item(0).firstChild.nodeValue
-            ret['detail'] = 
dom.getElementsByTagName('detail').item(0).firstChild.nodeValue
-
-        if action == 'ticket':
-            elem = dom.getElementsByTagName('ticket').item(0)
-            ret['value'] = 
elem.getElementsByTagName('value').item(0).firstChild.nodeValue
-            ret['expired'] = 
elem.getElementsByTagName('expiry').item(0).firstChild.nodeValue
-
-        return ret
diff --git a/python/WebHandler.py b/python/WebHandler.py
index b54f19e..a61b982 100644
--- a/python/WebHandler.py
+++ b/python/WebHandler.py
@@ -1,9 +1,9 @@
-import RestCommand
+import OVirtDispatcher
 
 import cgi
 import BaseHTTPServer
 
-restCommand = None
+dispatcher = None
 
 '''
 WebHandler: simple Web Server
@@ -18,6 +18,8 @@
         if self.path == '/':
             form = cgi.FieldStorage(fp=self.rfile, headers=self.headers, 
environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], 
})
             self._login_method(form)
+        elif self.path == '/uservms':
+            self._uservms_method()
         else:
             self._page_error()
 
@@ -32,6 +34,8 @@
 
         if p == '/':
             self._login_method()
+        elif p == '/uservms':
+            self._uservms_method()
         elif p == '/action':
             self._action_method(params)
         else:
@@ -45,9 +49,17 @@
         self.wfile.write("<body><p>Page not found %s</p>" % self.path)
         self.wfile.write("</body></html>")
 
+    def _failed_action(self, reason, detail):
+        return '''<html><body>
+        <p style='color:red'>Action failed!</p>
+        <br/>Reason: %s
+        <br/>Details: %s
+        <br/>
+        <button onclick=javascript:location.href='/uservms'>Back</button>
+        </body></html>''' % (reason, detail)
 
     def _action_method(self, params):
-        global restCommand
+        global dispatcher
         self.send_response(200)
         self.send_header("Content-type", "text/html")
         self.end_headers()
@@ -56,37 +68,44 @@
 
         vmid = form['vmid'][0]
         action = form['action'][0]
+        success = False
 
-        res = restCommand.runAction(vmid, action)
+        if action == 'start':
+            success, reason, detail = dispatcher.startVm(vmid)
+            if not success:
+                html = self._failed_action(reason, detail)
 
-        if res['status'] == 'failed':
-            html = '''<html><body>
-            <p style='color:red'>Action failed!</p>
-            <br/>Reason: %s
-            <br/>Details: %s
-            <br/>
-            <button onclick=javascript:history.back()>Back</button>
-            </body></html>''' % (res['reason'], res['detail'])
+        elif action == 'stop':
+            success, reason, detail = dispatcher.stopVm(vmid)
+            if not success:
+                html = self._failed_action(reason, detail)
 
         elif action == 'ticket':
-            vm = restCommand.getVmByVmId(vmid)
+            try:
+                value, expiry = dispatcher.ticketVm(vmid)
 
-            if self.headers['user-agent'].lower().find('windows') >= 0:
-                html = self._ticketIE(vm, res)
-            else:
-                html = self._ticketFirefox(vm, res)
+                vm = dispatcher.getVmById(vmid)
+                display = vm.get_display()
 
-        else:
+                if self.headers['user-agent'].lower().find('windows') >= 0:
+                    html = self._ticketIE(display.get_address(), 
display.get_port(), value)
+                else:
+                    html = self._ticketFirefox(display.get_address(), 
display.get_port(), value)
+            except Exception as e:
+                reason, detail = e.args
+                html = self._failed_action(reason, detail)
+
+        if success:
             html = '''<html><body>
             VM '%s' successfully
             <br/>
-            <button onclick=javascript:history.back()>Back</button>
+            <button onclick=javascript:location.href='/uservms'>Back</button>
             </body></html>
             ''' % action
 
         self.wfile.write(html)
 
-    def _ticketIE(self, vm, res):
+    def _ticketIE(self, host, port, password):
         html = '''<html>
    <script>
        function onConnect() {
@@ -97,17 +116,20 @@
        }
    </script>
 <body>
+    VMs ticket set:
+    <br/>
     <OBJECT style='visibility: hidden' codebase='SpiceX.cab#version=1,0,0,1' 
ID='spice' CLASSID='CLSID:ACD6D89C-938D-49B4-8E81-DDBD13F4B48A'>
     </OBJECT>
     <form>
         <input type=button onclick='javascript:onConnect();' value='Connect'/>
     </form>
+    <button onclick=javascript:location.href='/uservms'>Back</button>
 </body>
-</html>''' % (vm['address'], vm['port'], res['value'])
+</html>''' % (host, port, password)
 
         return html
 
-    def _ticketFirefox(self, vm, res):
+    def _ticketFirefox(self, host, port, password):
         html = '''<html>
    <script>
        function onConnect() {
@@ -119,24 +141,27 @@
        }
    </script>
 <body>
+    VMs ticket set:
+    <br/>
     <embed id='spice' type="application/x-spice" width=0 height=0><br>
     <form>
         <input type=button value='Connent' onclick='onConnect()'/>
     </form>
+    <button onclick=javascript:location.href='/uservms'>Back</button>
 </body>
-</html>''' % (vm['address'], vm['port'], res['value'])
+</html>''' % (host, port, password)
 
         return html
 
 
     def _uservms_method(self):
-        #form = cgi.FieldStorage(fp=self.rfile, headers=self.headers, 
environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], 
})
+        global dispatcher
 
         self.send_response(200)
         self.send_header("Content-type", "text/html")
         self.end_headers()
 
-        vms = restCommand.getUserVms()
+        vms = dispatcher.getUserVms()
 
         # render the html
         html = '''<html>
@@ -154,19 +179,9 @@
         '''
 
         for vm in vms:
-            startable = ''
-            if not vm['startable']:
-                startable = "disabled='disabled'"
-            stopable = ''
-            if not vm['stopable']:
-                stopable = "disabled='disabled'"
-            connectable = ''
-            if not vm['connectable'] or vm['display'] != 'spice':
-                connectable = "disabled='disabled'"
-
-            startbtn = "<button %s 
onclick=javascript:location.href='action?vmid=%s&action=start' 
type='button'>Start</button>" % (startable, vm['vmid'])
-            stopbtn = "<button %s 
onclick=javascript:location.href='action?vmid=%s&action=stop' 
type='button'>Stop</button>" % (stopable, vm['vmid'])
-            connectbtn = "<button %s 
onclick=javascript:location.href='action?vmid=%s&action=ticket' 
type='button'>Console</button>" % (connectable, vm['vmid'])
+            startbtn = "<button 
onclick=javascript:location.href='action?vmid=%s&action=start' 
type='button'>Start</button>" % (vm.get_id())
+            stopbtn = "<button 
onclick=javascript:location.href='action?vmid=%s&action=stop' 
type='button'>Stop</button>" % (vm.get_id())
+            connectbtn = "<button 
onclick=javascript:location.href='action?vmid=%s&action=ticket' 
type='button'>Console</button>" % (vm.get_id())
 
             html = html + '''       <tr>
             <td>%s</td>
@@ -175,22 +190,32 @@
             <td>%s</td>
             <td>%s</td>
             <td>%s</td>
-        </tr>''' % (vm['name'], vm['status'], vm['display'], startbtn, 
stopbtn, connectbtn)
+        </tr> ''' % (vm.get_name(), vm.get_status().get_state(), 
vm.get_display().get_type(), startbtn, stopbtn, connectbtn)
 
-        html = html + '''   </table></center></body></html>'''
+        html = html + '''
+        <tr>
+            <td><button 
onclick=javascript:location.href='/'>Logout</button></td>
+        </tr>
+        </table></center></body></html>'''
         self.wfile.write(html)
+
+    def _redirectTo(self, url, timeout=0):
+        self.send_response(200)
+        self.send_header("Content-type", "text/html")
+        self.end_headers()
+        self.wfile.write("""<html><head><meta HTTP-EQUIV="REFRESH" 
content="%i; url=%s"/></head></html>""" % (timeout, url))
 
 
     def _login_method(self, form={}):
-        global restCommand
+        global dispatcher
         message = ''
         if form.has_key("username") and form.has_key('password'):
-            restCommand = RestCommand.RestCommand()
-            if restCommand.login(form.getvalue("username"), 
form.getvalue("password")):
-                self._uservms_method()
+            dispatcher = OVirtDispatcher.OVirtDispatcher()
+            loggedin, message = dispatcher.login(form.getvalue("username"), 
form.getvalue("password"))
+
+            if loggedin:
+                self._redirectTo('/uservms')
                 return
-            else:
-                message = 'Login Error'
 
         self.send_response(200)
         self.send_header("Content-type", "text/html")


--
To view, visit http://gerrit.ovirt.org/10624
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8ab241473b714dacdf57909e02fe1cb579c252e6
Gerrit-PatchSet: 1
Gerrit-Project: samples-portals
Gerrit-Branch: master
Gerrit-Owner: Shahar Havivi <shav...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to