added rtapi, racktables api python module
authorRobert Vojcik <robert@vojcik.net>
Mon, 5 May 2014 14:45:29 +0000 (16:45 +0200)
committerRobert Vojcik <robert@vojcik.net>
Mon, 5 May 2014 14:45:29 +0000 (16:45 +0200)
rtapi/.gitignore [new file with mode: 0644]
rtapi/LICENSE [new file with mode: 0644]
rtapi/README.md [new file with mode: 0644]
rtapi/__init__.py [new file with mode: 0644]

diff --git a/rtapi/.gitignore b/rtapi/.gitignore
new file mode 100644 (file)
index 0000000..51cbe85
--- /dev/null
@@ -0,0 +1,54 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+bin/
+build/
+develop-eggs/
+dist/
+eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# Rope
+.ropeproject
+
+# Django stuff:
+*.log
+*.pot
+
+# Sphinx documentation
+docs/_build/
+
diff --git a/rtapi/LICENSE b/rtapi/LICENSE
new file mode 100644 (file)
index 0000000..22fbe5d
--- /dev/null
@@ -0,0 +1,339 @@
+GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    {description}
+    Copyright (C) {year}  {fullname}
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  {signature of Ty Coon}, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
\ No newline at end of file
diff --git a/rtapi/README.md b/rtapi/README.md
new file mode 100644 (file)
index 0000000..e970562
--- /dev/null
@@ -0,0 +1,180 @@
+rtapi
+=====
+
+Racktables API
+
+Python module for accessing and manipulating racktables objects.
+
+Dependency
+------------------
+
+* ipaddr module - https://code.google.com/p/ipaddr-py/
+
+This module must be installed along with rtapi.
+
+Installation
+----------------
+Simply copy rtapi and ipaddr into your projects folder or in place from where your project importing python modules.
+
+
+Class manual
+--------------------
+    NAME
+       rtapi
+
+    FILE
+        /home/wire/Projects/rtapi/__init__.py
+    
+    DESCRIPTION
+        PyRacktables
+        Simple python Class for manipulation with objects in racktables database. 
+    
+        For proper function, some methods need ipaddr module (https://pypi.python.org/pypi/ipaddr)
+
+    PACKAGE CONTENTS
+
+
+    CLASSES
+        RTObject
+    
+    class RTObject
+     |  Ractables object. Require database object as argument.
+     |  
+     |  Methods defined here:
+     |  
+     |  AddObject(self, name, server_type_id, asset_no, label)
+     |      Add new object to racktables
+     |  
+     |  AssignChassisSlot(chassis_name, slot_number, server_name)
+     |      Assign server objects to server chassis
+     |  
+     |  CleanIPAddresses(self, object_id, ip_addresses, device)
+     |      Clean unused ip from object. ip addresses is list of IP addresses configured on device (device) on host (object_id)
+     |  
+     |  CleanIPv6Addresses(self, object_id, ip_addresses, device)
+     |      Clean unused ipv6 from object. ip_addresses mus be list of active IP addresses on device (device) on host (object_id)
+     |  
+     |  CleanVirtuals(self, object_id, virtual_servers)
+     |      Clean dead virtuals from hypervisor. virtual_servers is list of active virtual servers on hypervisor (object_id)
+     |  
+     |  GetAllServerChassisId(self)
+     |      Get list of all server chassis IDs
+     |  
+     |  GetAttributeId(self, searchstring)
+     |      Search racktables database and get attribud id based on search string as argument
+     |  
+     |  GetDictionaryId(self, searchstring)
+     |      Search racktables dictionary using searchstring and return id of dictionary element
+     |  
+     |  GetInterfaceId(self, object_id, interface)
+     |      Find id of specified interface
+     |  
+     |  GetInterfaceName(self, object_id, interface_id)
+     |      Find name of specified interface. Required object_id and interface_id argument
+     |  
+     |  GetObjectComment(self, object_id)
+     |      Get object comment
+     |  
+     |  GetObjectId(self, name)
+     |      Translate Object name to object id
+     |  
+     |  GetObjectLabel(self, object_id)
+     |      Get object label
+     |  
+     |  GetObjectName(self, object_id)
+     |      Translate Object ID to Object Name
+     |  
+     |  InsertAttribute(self, object_id, object_tid, attr_id, string_value, uint_value, name)
+     |      Add or Update object attribute. 
+     |      Require 6 arguments: object_id, object_tid, attr_id, string_value, uint_value, name
+     |  
+     |  InsertLog(object_id, message)
+     |      Attach log message to specific object
+     |  
+     |  InterfaceAddIpv4IP(self, object_id, device, ip)
+     |      Add/Update IPv4 IP on interface
+     |  
+     |  InterfaceAddIpv6IP(self, object_id, device, ip)
+     |      Add/Update IPv6 IP on interface
+     |  
+     |  LinkNetworkInterface(self, object_id, interface, switch_name, interface_switch)
+     |      Link two devices togetger
+     |  
+     |  LinkVirtualHypervisor(self, object_id, virtual_id)
+     |      Assign virtual server to correct hypervisor
+     |  
+     |  ListObjects(self)
+     |      List all objects
+     |  
+     |  ObjectExistName(self, name)
+     |      Check if object exist in database based on name
+     |  
+     |  ObjectExistST(self, service_tag)
+     |      Check if object exist in database based on asset_no
+     |  
+     |  ObjectExistSTName(self, name, asset_no)
+     |      Check if object exist in database based on name
+     |  
+     |  UpdateNetworkInterface(self, object_id, interface)
+     |      Add network interfece to object if not exist
+     |  
+     |  UpdateObjectComment(self, object_id, comment)
+     |      Update comment on object
+     |  
+     |  UpdateObjectLabel(self, object_id, label)
+     |      Update label on object
+     |  
+     |  UpdateObjectName(self, object_id, name)
+     |      Update name on object
+     |  
+     |  __init__(self, dbobject)
+     |      Initialize Object
+     |  
+     |  db_fetch_lastid(self)
+     |      SQL function which return ID of last inserted row.
+     |  
+     |  db_insert(self, sql)
+     |      SQL insert/update function. Require sql query as parameter
+     |  
+     |  db_query_all(self, sql)
+     |      SQL query function, return all rows. Require sql query as parameter
+     |  
+     |  db_query_one(self, sql)
+     |      SQL query function, return one row. Require sql query as parameter
+
+    DATA
+        __all__ = ['RTObject']
+        __author__ = 'Robert Vojcik (robert@vojcik.net)'
+        __copyright__ = 'OpenSource'
+        __license__ = 'GPLv2'
+        __version__ = '0.0.1'
+
+    VERSION
+        0.0.1
+
+    AUTHOR
+        Robert Vojcik (robert@vojcik.net)
+
+Example
+-------
+
+
+    import ipaddr
+    import MySQLdb
+    import rtapi
+
+    # Create connection to database
+    try:
+        # Create connection to database
+        db = MySQLdb.connect(host='hostname',port=3306, passwd='mypass',db='racktables',user='racktables)
+    except MySQLdb.Error ,e:
+        print "Error %d: %s" % (e.args[0],e.args[1])
+        sys.exit(1)
+
+    # Initialize rtapi with database connection
+    rt = rtapi.RTObject(db)
+
+    # List all objects from database
+    print rt.ListObjects()
+
+
diff --git a/rtapi/__init__.py b/rtapi/__init__.py
new file mode 100644 (file)
index 0000000..45325eb
--- /dev/null
@@ -0,0 +1,532 @@
+#!/usr/bin/python
+#
+#   RTAPI
+#   Racktables API is simple python module providing some methods 
+#   for monipulation with racktables objects.
+#
+#   This utility is released under GPL v2
+#   
+#   Server Audit utility for Racktables Datacenter management project.
+#   Copyright (C) 2012  Robert Vojcik (robert@vojcik.net)
+#   
+#   This program is free software; you can redistribute it and/or
+#   modify it under the terms of the GNU General Public License
+#   as published by the Free Software Foundation; either version 2
+#   of the License, or (at your option) any later version.
+#   
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#   
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+'''PyRacktables
+Simple python Class for manipulation with objects in racktables database. 
+
+For proper function, some methods need ipaddr module (https://pypi.python.org/pypi/ipaddr)
+'''
+__author__ = "Robert Vojcik (robert@vojcik.net)"
+__version__ = "0.1.1"
+__copyright__ = "OpenSource"
+__license__ = "GPLv2"
+
+__all__ = ["RTObject"]
+
+
+import re
+import ipaddr
+
+
+class RTObject:
+    '''Ractables object. Require database object as argument. '''
+
+    # Init method
+    def __init__(self, dbobject):
+        '''Initialize Object'''
+        # Open configuration file
+        self.db = dbobject
+        self.dbresult = self.db.cursor()
+
+    # DATABASE methods
+    def db_query_one(self, sql):
+        '''SQL query function, return one row. Require sql query as parameter'''
+        self.dbresult.execute(sql)
+        return self.dbresult.fetchone()
+
+    def db_query_all(self, sql):
+        '''SQL query function, return all rows. Require sql query as parameter'''
+        self.dbresult.execute(sql)
+        return self.dbresult.fetchall()
+    
+    def db_insert(self, sql):
+        '''SQL insert/update function. Require sql query as parameter'''
+        self.dbresult.execute(sql)
+        self.db.commit()
+
+    def db_fetch_lastid(self):
+        '''SQL function which return ID of last inserted row.'''
+        return self.dbresult.lastrowid
+    
+    def ListObjects(self):
+        '''List all objects'''
+        sql = 'SELECT name FROM Object'
+        return "Found " + str(len(self.db_query_all(sql))) +" objects in database" 
+
+    # Object methotds
+    def ObjectExistST(self,service_tag):
+        '''Check if object exist in database based on asset_no'''
+        sql = 'SELECT name FROM Object WHERE asset_no = \''+service_tag+'\''
+        if self.db_query_one(sql) == None:
+            return False
+        else:
+            return True
+    
+    def ObjectExistName(self,name):
+        '''Check if object exist in database based on name'''
+        sql = 'select id from Object where name = \''+name+'\''
+        if self.db_query_one(sql) == None:
+            return False
+        else:
+            return True
+
+    def ObjectExistSTName(self,name,asset_no):
+        '''Check if object exist in database based on name'''
+        sql = "SELECT id FROM Object WHERE name = '%s' AND asset_no = '%s'" % (name,asset_no)
+        if self.db_query_one(sql) == None:
+            return False
+        else:
+            return True
+
+    def AddObject(self,name,server_type_id,asset_no,label):
+        '''Add new object to racktables'''
+        sql = "INSERT INTO Object (name,objtype_id,asset_no,label) VALUES ('%s',%d,'%s','%s')" % (name,server_type_id,asset_no,label)
+        self.db_insert(sql)
+
+    def UpdateObjectLabel(self,object_id,label):
+        '''Update label on object'''
+        sql = "UPDATE Object SET label = '%s' where id = %d" % (label, object_id)
+        self.db_insert(sql)
+    
+    def UpdateObjectComment(self,object_id,comment):
+        '''Update comment on object'''
+        sql = "UPDATE Object SET comment = '%s' where id = %d" % (comment, object_id)
+        self.db_insert(sql)
+
+    def UpdateObjectName(self,object_id,name):
+        '''Update name on object'''
+        sql = "UPDATE Object SET name = '%s' where id = %d" % (name, object_id)
+        self.db_insert(sql)
+
+    def GetObjectName(self,object_id):
+        '''Translate Object ID to Object Name'''
+        #Get interface id
+        sql = "SELECT name FROM Object WHERE id = %d" % (object_id)
+        result = self.db_query_one(sql)
+        if result != None:
+            object_name = result[0]
+        else:
+            object_name = None
+
+        return object_name
+    
+    def GetObjectLabel(self,object_id):
+        '''Get object label'''
+        #Get interface id
+        sql = "SELECT label FROM Object WHERE id = %d" % (object_id)
+        result = self.db_query_one(sql)
+        if result != None:
+            object_label = result[0]
+        else:
+            object_label = None
+
+        return object_label
+
+    def GetObjectComment(self,object_id):
+        '''Get object comment'''
+        #Get interface id
+        sql = "SELECT comment FROM Object WHERE id = %d" % (object_id)
+        result = self.db_query_one(sql)
+        if result != None:
+            object_comment = result[0]
+        else:
+            object_comment = None
+
+        return object_comment
+
+    def GetObjectId(self,name):
+        '''Translate Object name to object id'''
+        #Get interface id
+        sql = "SELECT id FROM Object WHERE name = '%s'" % (name)
+        result = self.db_query_one(sql)
+        if result != None:
+            object_id = result[0]
+        else:
+            object_id = None
+
+        return object_id
+
+    # Logging
+    def InsertLog(object_id,message):
+        '''Attach log message to specific object'''
+        sql = "INSERT INTO ObjectLog (object_id,user,date,content) VALUES (%d,'script',now(),'%s')" % (object_id, message)
+        self.db_insert(sql)
+
+    # Attrubute methods
+    def InsertAttribute(self,object_id,object_tid,attr_id,string_value,uint_value,name):
+        '''Add or Update object attribute. 
+        Require 6 arguments: object_id, object_tid, attr_id, string_value, uint_value, name'''
+    
+        # Check if attribute exist
+        sql = "SELECT string_value,uint_value FROM AttributeValue WHERE object_id = %d AND object_tid = %d AND attr_id = %d" % (object_id, object_tid, attr_id)
+        result = self.db_query_one(sql)
+
+        if result != None:
+            # Check if attribute value is same and determine attribute type
+            old_string_value = result[0]
+            old_uint_value = result[1]
+            same_flag = "no"
+            attribute_type = "None"
+
+            if old_string_value != None:
+                attribute_type = "string"
+                old_value = old_string_value
+                if old_string_value == string_value:
+                    same_flag = "yes"
+            elif old_uint_value != None:
+                attribute_type = "uint"
+                old_value = old_uint_value
+                if old_uint_value == uint_value:
+                    same_flag = "yes"
+
+            # If exist, update value
+            new_value = ''
+            if same_flag == "no":
+                if attribute_type == "string":
+                    sql = "UPDATE AttributeValue SET string_value = '%s' WHERE object_id = %d AND attr_id = %d AND object_tid = %d" % (string_value, object_id, attr_id, object_tid)
+                    new_value = string_value
+                if attribute_type == "uint":
+                    sql = "UPDATE AttributeValue SET uint_value = %d WHERE object_id = %d AND attr_id = %d AND object_tid = %d" % (uint_value, object_id, attr_id, object_tid)
+                    new_value = uint_value
+
+                self.db_insert(sql)
+
+        else:
+            # Attribute not exist, insert new
+            if string_value == "NULL":
+                sql = "INSERT INTO AttributeValue (object_id,object_tid,attr_id,uint_value) VALUES (%d,%d,%d,%d)" % (object_id,object_tid,attr_id,uint_value)
+            else:
+                sql = "INSERT INTO AttributeValue (object_id,object_tid,attr_id,string_value) VALUES (%d,%d,%d,'%s')" % (object_id,object_tid,attr_id,string_value)
+            self.db_insert(sql)
+
+    def GetAttributeId(self,searchstring):
+        '''Search racktables database and get attribud id based on search string as argument'''
+        sql = "SELECT id FROM Attribute WHERE name LIKE '%"+searchstring+"%'"
+  
+        result = self.db_query_one(sql)
+
+        if result != None:
+            getted_id = result[0]
+        else:
+            getted_id = None
+
+        return getted_id
+
+    # Interfaces methods
+    def GetInterfaceName(self,object_id,interface_id):
+        '''Find name of specified interface. Required object_id and interface_id argument'''
+        #Get interface id
+        sql = "SELECT name FROM Port WHERE object_id = %d AND name = %d" % (object_id, interface_id)
+        result = self.db_query_one(sql)
+        if result != None:
+            port_name = result[0]
+        else:
+            port_name = None
+
+        return port_name
+
+    def GetInterfaceId(self,object_id,interface):
+        '''Find id of specified interface'''
+        #Get interface id
+        sql = "SELECT id,name FROM Port WHERE object_id = %d AND name = '%s'" % (object_id, interface)
+        result = self.db_query_one(sql)
+        if result != None:
+            port_id = result[0]
+        else:
+            port_id = None
+
+        return port_id
+
+    def UpdateNetworkInterface(self,object_id,interface):
+        '''Add network interfece to object if not exist'''
+
+        sql = "SELECT id,name FROM Port WHERE object_id = %d AND name = '%s'" % (object_id, interface)
+
+        result = self.db_query_one(sql)
+        if result == None:
+        
+            sql = "INSERT INTO Port (object_id,name,iif_id,type) VALUES (%d,'%s',1,24)" % (object_id,interface)
+            self.db_insert(sql)
+            port_id = self.db_getlastrowid()
+
+        else:
+            port_id = result[0]
+
+
+        return port_id
+
+    def LinkNetworkInterface(self,object_id,interface,switch_name,interface_switch):
+        '''Link two devices togetger'''
+        #Get interface id
+        port_id = self.GetInterfaceId(object_id,interface)
+        if port_id != None:
+            #Get switch object ID
+            switch_object_id = self.GetObjectId(switch_name)
+            if switch_object_id != None:
+                switch_port_id = self.GetInterfaceId(switch_object_id,interface_switch)
+                if switch_port_id != None:
+                    if switch_port_id > port_id:
+                        select_object = 'portb'
+                    else:
+                        select_object = 'porta'
+                    sql = "SELECT %s FROM Link WHERE porta = %d OR portb = %d" % (select_object, port_id, port_id)
+                    result = self.db_query_one(sql)
+                    if result == None:
+                        #Insert new connection
+                        sql = "INSERT INTO Link (porta,portb) VALUES (%d,%d)" % (port_id, switch_port_id)
+                        self.db_insert(sql)
+                        resolution = True
+                    else:
+                        #Update old connection
+                        old_switch_port_id = result[0]
+                        if old_switch_port_id != switch_port_id:
+                            sql = "UPDATE Link set portb = %d, porta = %d WHERE porta = %d OR portb = %d" % (switch_port_id,port_id, port_id, port_id)
+                            self.db_insert(sql)
+                            sql = "SELECT Port.name as port_name, Object.name as obj_name FROM Port INNER JOIN Object ON Port.object_id = Object.id WHERE Port.id = %d" % old_switch_port_id
+                            result = self.db_query_one(sql)
+                            old_switch_port, old_device_link = result
+
+                            text = "Changed link from %s -> %s" % (old_device_link,old_switch_port)
+                            self.InsertLog(object_id,text)
+                            resolution = True
+                        resolution = None
+
+                else:
+                    resolution = None
+            else:
+                resolution = None
+
+        else:
+            resolution = None
+
+        return resolution
+
+    def InterfaceAddIpv4IP(self,object_id,device,ip):
+        '''Add/Update IPv4 IP on interface'''
+
+        sql = "SELECT INET_NTOA(ip) from IPv4Allocation WHERE object_id = %d AND name = '%s'" % (object_id,device)
+        result = self.db_query_all(sql)
+
+        if result != None:
+            old_ips = result
+        
+        is_there = "no"
+            
+        for old_ip in old_ips:
+            if old_ip[0] == ip:
+                is_there = "yes"
+
+        if is_there == "no":
+            sql = "INSERT INTO IPv4Allocation (object_id,ip,name) VALUES (%d,INET_ATON('%s'),'%s')" % (object_id,ip,device)
+            self.db_insert(sql)
+            text = "Added IP %s on %s" % (ip,device)
+            self.InsertLog(object_id,text)
+
+    def InterfaceAddIpv6IP(self,object_id,device,ip):
+        '''Add/Update IPv6 IP on interface'''
+        #Create address object using ipaddr 
+        addr6 = ipaddr.IPAddress(ip)
+        #Create IPv6 format for Mysql
+        ip6 = "".join(str(x) for x in addr6.exploded.split(':'))
+
+        sql = "SELECT HEX(ip) FROM IPv6Allocation WHERE object_id = %d AND name = '%s'" % (object_id, device)
+        result = self.db_query_all(sql)
+        
+        if result != None:
+            old_ips = result
+
+        is_there = "no"
+
+        for old_ip in old_ips:
+            if old_ip[0] != ip6:
+                is_there = "yes"
+
+        if is_there == "no":
+            sql = "INSERT INTO IPv6Allocation (object_id,ip,name) VALUES (%d,UNHEX('%s'),'%s')" % (object_id,ip6,device)
+            self.db_insert(sql)
+            text = "Added IPv6 IP %s on %s" % (ip,device)
+            self.InsertLog(object_id,text)
+
+
+    
+    def GetDictionaryId(self,searchstring):
+        '''Search racktables dictionary using searchstring and return id of dictionary element'''
+        sql = "SELECT dict_key FROM Dictionary WHERE dict_value LIKE '%"+searchstring+"%'"
+
+        result = self.db_query_one(sql)
+        if result != None:
+            getted_id = result[0]
+        else:
+            getted_id = None
+
+        return getted_id
+
+    def CleanVirtuals(self,object_id,virtual_servers):
+        '''Clean dead virtuals from hypervisor. virtual_servers is list of active virtual servers on hypervisor (object_id)'''
+
+        sql = "SELECT child_entity_id FROM EntityLink WHERE parent_entity_id = %d" % object_id
+
+        result = self.db_query_all(sql)
+
+        if result != None:
+            old_virtuals_ids = result
+            delete_virtual_id = []
+            new_virtuals_ids = []
+            # Translate names into ids
+            for new_virt in virtual_servers:
+                new_id = self.GetObjectId(new_virt)
+                if new_id != None:
+                    new_virtuals_ids.append(new_id)
+
+            for old_id in old_virtuals_ids:
+                try:
+                    test = new_virtuals_ids.index(old_id[0])
+                except ValueError:
+                    delete_virtual_id.append(old_id[0]) 
+        if len(delete_virtual_id) != 0:
+            for virt_id in delete_virtual_id:
+
+                sql = "DELETE FROM EntityLink WHERE parent_entity_id = %d AND child_entity_id = %d" % (object_id,virt_id)
+                self.db_insert(sql)
+                virt_name = self.GetObjectName(virt_id)
+                logstring = "Removed virtual %s" % virt_name
+                self.InsertLog(object_id,logstring)
+
+    def CleanIPAddresses(self,object_id,ip_addresses,device):
+        '''Clean unused ip from object. ip addresses is list of IP addresses configured on device (device) on host (object_id)'''
+
+        sql = "SELECT INET_NTOA(ip) FROM IPv4Allocation WHERE object_id = %d AND name = '%s'" % (object_id, device)
+        
+        result = self.db_query_all(sql)
+
+        if result != None:
+            old_ips = result
+            delete_ips = []
+
+            for old_ip in old_ips:
+                try:
+                    test = ip_addresses.index(old_ip[0])
+                except ValueError:
+                    delete_ips.append(old_ip[0]) 
+        if len(delete_ips) != 0:
+            for ip in delete_ips:
+                sql = "DELETE FROM IPv4Allocation WHERE ip = INET_ATON('%s') AND object_id = %d AND name = '%s'" % (ip,object_id,device)
+                self.db_insert(sql)
+                logstring = "Removed IP %s from %s" % (ip,device)
+                self.InsertLog(object_id,logstring)
+
+    def CleanIPv6Addresses(self,object_id,ip_addresses,device):
+        '''Clean unused ipv6 from object. ip_addresses mus be list of active IP addresses on device (device) on host (object_id)'''
+
+        sql = "SELECT HEX(ip) FROM IPv6Allocation WHERE object_id = %d AND name = '%s'" % (object_id,device)
+        result = self.db_query_all(sql)
+
+        if result != None:
+            old_ips = result
+            delete_ips = []
+            new_ip6_ips = []
+
+            #We must prepare ipv6 addresses into same format for compare
+            for new_ip in ip_addresses:
+                converted = ipaddr.IPAddress(new_ip).exploded.lower()
+                new_ip6_ips.append(converted)
+
+
+            for old_ip_hex in old_ips:
+                try:
+                    #First we must construct IP from HEX
+                    tmp = re.sub("(.{4})","\\1:", old_ip_hex[0], re.DOTALL)
+                    #Remove last : and lower string
+                    old_ip = tmp[:len(tmp)-1].lower()
+
+                    test = new_ip6_ips.index(old_ip)
+
+                except ValueError:
+                    delete_ips.append(old_ip)
+
+        if len(delete_ips) != 0:
+            for ip in delete_ips:
+                db_ip6_format = "".join(str(x) for x in ip.split(':')) 
+                sql = "DELETE FROM IPv6Allocation WHERE ip = UNHEX('%s') AND object_id = %d AND name = '%s'" % (db_ip6_format,object_id,device)
+                self.db_insert(sql)
+                logstring = "Removed IP %s from %s" % (ip,device)
+                self.InsertLog(object_id,logstring)
+
+    def LinkVirtualHypervisor(self,object_id,virtual_id):
+        '''Assign virtual server to correct hypervisor'''
+        sql = "SELECT child_entity_id FROM EntityLink WHERE parent_entity_id = %d AND child_entity_id = %d" % (object_id,virtual_id)
+        result = self.db_query_one(sql)
+
+        if result == None:
+            sql = "INSERT INTO EntityLink (parent_entity_type, parent_entity_id, child_entity_type, child_entity_id) VALUES ('object',%d,'object',%d)" % (object_id, virtual_id)
+            self.db_insert(sql)
+            text = "Linked virtual %s with hypervisor" % self.GetObjectName(virtual_id)
+            self.InsertLog(object_id,text)
+
+    def AssignChassisSlot(self,chassis_name,slot_number,server_name):
+        '''Assign server objects to server chassis'''
+        chassis_id = self.GetObjectId(chassis_name)
+        server_id = self.GetObjectId(server_name)
+        slot_attribute_id = self.GetAttributeId("Slot number")
+
+        # Assign slot number to server
+        sql = "INSERT INTO AttributeValue (object_id,object_tid,attr_id,string_value) VALUES ( %d, 4, %d, '%s')" % ( server_id, slot_attribute_id, slot_number)
+        try:
+            self.db_insert(sql)
+        except:
+            pass
+
+        # Assign server to chassis
+        # Check if it's connected
+        sql = "SELECT parent_entity_id FROM EntityLink WHERE child_entity_type = 'object' AND child_entity_id = %d" % (server_id)
+        result = self.db_query_one(sql)
+
+        if result != None:
+        # Object is connected to someone
+            if result[0] != chassis_id:
+            # Connected to differend chassis/chassis
+                sql = "UPDATE EntityLink SET parent_entity_id = %d WHERE child_entity_id = %d AND child_entity_type = 'object' AND parent_entity_id = %d" % (chassis_id, server_id, result[0])
+                self.db_insert(sql)
+
+                old_object_name = self.GetObjectName(result[0])
+                self.InsertLog(old_object_name, "Unlinked server %s" % (server_name))
+                self.InsertLog(server_id, "Unlinked from Blade Chassis %s" % (old_object_name))
+                self.InsertLog(chassis_id, "Linked with server %s" % (server_name))
+                self.InsertLog(server_id, "Linked with Blade Chassis %s" % (chassis_name))
+        
+        else:
+        # Object is not connected
+            sql = "INSERT INTO EntityLink (parent_entity_type, parent_entity_id, child_entity_type, child_entity_id) VALUES ('object', %d, 'object', %d)" % (chassis_id, server_id)
+            self.db_insert(sql)
+            self.InsertLog(chassis_id, "Linked with server %s" % (server_name))
+            self.InsertLog(server_id, "Linked with Blade Chassis %s" % (chassis_name))
+            
+            
+
+    def GetAllServerChassisId(self):
+        '''Get list of all server chassis IDs'''
+        sql = "SELECT object_id FROM AttributeValue WHERE attr_id = 2 AND uint_value = 994"
+        return self.db_query_all(sql)