#
# Thierry Parmentelat - INRIA
#
-from types import NoneType
+# pylint: disable=c0103, c0111
from PLC.Faults import *
from PLC.AuthorizeHelpers import AuthorizeHelpers
# known classes : { class -> details }
-taggable_classes = { Node : {'table_class' : Nodes,
- 'joins_class' : NodeTags, 'join_class' : NodeTag,
- 'secondary_key': 'hostname'},
- Interface : {'table_class' : Interfaces,
- 'joins_class': InterfaceTags, 'join_class': InterfaceTag,
- 'secondary_key' : 'ip'},
- Slice: {'table_class' : Slices,
- 'joins_class': SliceTags, 'join_class': SliceTag,
- 'secondary_key':'name'},
- Site: {'table_class' : Sites,
- 'joins_class': SiteTags, 'join_class': SiteTag,
- 'secondary_key':'login_base'},
- Person: {'table_class' : Persons,
- 'joins_class': PersonTags, 'join_class': PersonTag,
- 'secondary_key':'email'},
- }
+taggable_classes = {
+ Node : {'table_class' : Nodes,
+ 'joins_class' : NodeTags, 'join_class' : NodeTag,
+ 'secondary_key': 'hostname'},
+ Interface : {'table_class' : Interfaces,
+ 'joins_class': InterfaceTags, 'join_class': InterfaceTag,
+ 'secondary_key' : 'ip'},
+ Slice: {'table_class' : Slices,
+ 'joins_class': SliceTags, 'join_class': SliceTag,
+ 'secondary_key':'name'},
+ Site: {'table_class' : Sites,
+ 'joins_class': SiteTags, 'join_class': SiteTag,
+ 'secondary_key':'login_base'},
+ Person: {'table_class' : Persons,
+ 'joins_class': PersonTags, 'join_class': PersonTag,
+ 'secondary_key':'email'},
+}
# xxx probably defined someplace else
admin_roles = ['admin']
-person_roles = [ 'admin', 'pi', 'tech', 'user' ]
-all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ]
-tech_roles = [ 'admin', 'pi', 'tech' ]
+person_roles = ['admin', 'pi', 'tech', 'user']
+all_roles = ['admin', 'pi', 'tech', 'user', 'node']
+tech_roles = ['admin', 'pi', 'tech']
#
# generates 2 method classes:
#
# in addition a convenience method like e.g. LocateNodeArch is defined
# in the Accessor class; its purpose is to retrieve the tag, or to create it if needed
-#
+#
# Legacy NOTE:
# prior to plcapi-5.0-19, this used to accept an additional argument
# named min_role_id; this was redundant and confusing, it has been
# you then end up with e.g. GetPersonMyStuff
# the entry point accepts a single class or a list of classes
-def define_accessors (module, objclasses, *args, **kwds):
- if not isinstance(objclasses,list):
- objclasses=[objclasses]
+def define_accessors(module, objclasses, *args, **kwds):
+ if not isinstance(objclasses, list):
+ objclasses = [objclasses]
for objclass in objclasses:
- define_accessors_ (module, objclass, *args, **kwds)
+ define_accessors_(module, objclass, *args, **kwds)
# this is for one class
-def define_accessors_ (module, objclass, methodsuffix, tagname,
- category, description,
- get_roles=all_roles, set_roles=admin_roles,
- expose_in_api = False):
+def define_accessors_(module, objclass, methodsuffix, tagname,
+ category, description,
+ get_roles=all_roles, set_roles=admin_roles,
+ expose_in_api=False):
if objclass not in taggable_classes:
try:
# side-effect on, say, Node.tags, if required
if expose_in_api:
- getattr(objclass,'tags')[tagname]=Parameter(str,"accessor")
+ getattr(objclass, 'tags')[tagname] = Parameter(str, "accessor")
- classname=objclass.__name__
+ classname = objclass.__name__
get_name = "Get" + classname + methodsuffix
set_name = "Set" + classname + methodsuffix
locator_name = "Locate" + classname + methodsuffix
# accessor method objects under PLC.Method.Method
- get_class = type (get_name, (Method,),
- {"__doc__":"Accessor 'get' method designed for %s objects using tag %s"%\
- (classname,tagname)})
- set_class = type (set_name, (Method,),
- {"__doc__":"Accessor 'set' method designed for %s objects using tag %s"%\
- (classname,tagname)})
+ get_class = type(get_name, (Method,),
+ {"__doc__":
+ "Accessor 'get' method designed for %s objects using tag %s"%\
+ (classname, tagname)})
+ set_class = type(set_name, (Method,),
+ {"__doc__":
+ "Accessor 'set' method designed for %s objects using tag %s"%\
+ (classname, tagname)})
# accepts
- get_accepts = [ Auth () ]
- primary_key=objclass.primary_key
+ get_accepts = [Auth()]
+ primary_key = objclass.primary_key
secondary_key = taggable_classes[objclass]['secondary_key']
- get_accepts += [ Mixed (objclass.fields[primary_key], objclass.fields[secondary_key]) ]
+ get_accepts += [Mixed(objclass.fields[primary_key], objclass.fields[secondary_key])]
# for set, idem set of arguments + one additional arg, the new value
- set_accepts = get_accepts + [ Parameter (str,"New tag value") ]
+ set_accepts = get_accepts + [Parameter(str, "New tag value")]
# returns
- get_returns = Mixed (Parameter (str), Parameter(NoneType))
- set_returns = Parameter(NoneType)
+ get_returns = Mixed(Parameter(str), Parameter(type(None)))
+ set_returns = Parameter(type(None))
# store in classes
- setattr(get_class,'roles',get_roles)
- setattr(get_class,'accepts',get_accepts)
- setattr(get_class,'returns', get_returns)
+ setattr(get_class, 'roles', get_roles)
+ setattr(get_class, 'accepts', get_accepts)
+ setattr(get_class, 'returns', get_returns)
# that was useful for legacy method only, but we now need type_checking
# setattr(get_class,'skip_type_check',True)
- setattr(set_class,'roles',set_roles)
- setattr(set_class,'accepts',set_accepts)
- setattr(set_class,'returns', set_returns)
+ setattr(set_class, 'roles', set_roles)
+ setattr(set_class, 'accepts', set_accepts)
+ setattr(set_class, 'returns', set_returns)
# that was useful for legacy method only, but we now need type_checking
# setattr(set_class,'skip_type_check',True)
# locate the tag and create it if needed
# this method is attached to the Accessor class
- def tag_locator (self, enforce=False):
- return self.locate_or_create_tag (tagname=tagname,
- category=category,
- description=description,
- roles=set_roles,
- enforce=enforce)
+ def tag_locator(self, enforce=False):
+ return self.locate_or_create_tag(
+ tagname=tagname,
+ category=category,
+ description=description,
+ roles=set_roles,
+ enforce=enforce)
# attach it to the Accessor class
- Accessor.register_tag_locator(locator_name,tag_locator)
+ Accessor.register_tag_locator(locator_name, tag_locator)
# body of the get method
- def get_call (self, auth, id_or_name):
+ def get_call(self, auth, id_or_name):
# locate the tag, see above
tag_locator = Accessor.retrieve_tag_locator(locator_name)
tag_type = tag_locator(AccessorSingleton(self.api))
- tag_type_id=tag_type['tag_type_id']
+ tag_type_id = tag_type['tag_type_id']
- filter = {'tag_type_id':tag_type_id}
- if isinstance (id_or_name,int):
- filter[primary_key]=id_or_name
+ filter = {'tag_type_id': tag_type_id}
+ if isinstance(id_or_name, int):
+ filter[primary_key] = id_or_name
else:
- filter[secondary_key]=id_or_name
- joins = joins_class (self.api,filter,['value'])
+ filter[secondary_key] = id_or_name
+ joins = joins_class(self.api, filter, ['value'])
if not joins:
# xxx - we return None even if id_or_name is not valid
return None
return joins[0]['value']
# attach it
- setattr (get_class,"call",get_call)
+ setattr(get_class, "call", get_call)
# body of the set method
- def set_call (self, auth, id_or_name, value):
+ def set_call(self, auth, id_or_name, value):
# locate the object
- if isinstance (id_or_name, int):
- filter={primary_key:id_or_name}
+ if isinstance(id_or_name, int):
+ filter = {primary_key:id_or_name}
else:
- filter={secondary_key:id_or_name}
+ filter = {secondary_key:id_or_name}
# we need the full monty b/c of the permission system
# objs = table_class(self.api, filter,[primary_key,secondary_key])
objs = table_class(self.api, filter)
if not objs:
- raise PLCInvalidArgument("Cannot set tag on %s %r"%(objclass.__name__,id_or_name))
+ raise PLCInvalidArgument("Cannot set tag on %s %r"%(objclass.__name__, id_or_name))
# the object being tagged
- obj=objs[0]
+ obj = objs[0]
primary_id = obj[primary_key]
# locate the tag, see above
tag_type_id = tag_type['tag_type_id']
# check authorization
- if not hasattr(objclass,'caller_may_write_tag'):
- raise PLCAuthenticationFailure("class %s misses method caller_may_write_tag"%objclass.__name__)
- obj.caller_may_write_tag (self.api,self.caller,tag_type)
+ if not hasattr(objclass, 'caller_may_write_tag'):
+ raise PLCAuthenticationFailure(
+ "class %s misses method caller_may_write_tag"%objclass.__name__)
+ obj.caller_may_write_tag(self.api, self.caller, tag_type)
# locate the join object (e.g. NodeTag or similar)
- filter = {'tag_type_id':tag_type_id}
- if isinstance (id_or_name,int):
- filter[primary_key]=id_or_name
+ filter = {'tag_type_id': tag_type_id}
+ if isinstance(id_or_name, int):
+ filter[primary_key] = id_or_name
else:
- filter[secondary_key]=id_or_name
- joins = joins_class (self.api,filter)
+ filter[secondary_key] = id_or_name
+ joins = joins_class(self.api, filter)
# setting to something non void
if value is not None:
if not joins:
- join = join_class (self.api)
- join['tag_type_id']=tag_type_id
- join[primary_key]=primary_id
- join['value']=value
+ join = join_class(self.api)
+ join['tag_type_id'] = tag_type_id
+ join[primary_key] = primary_id
+ join['value'] = value
join.sync()
else:
- joins[0]['value']=value
+ joins[0]['value'] = value
joins[0].sync()
# providing an empty value means clean up
else:
if joins:
- join=joins[0]
+ join = joins[0]
join.delete()
# log it
- self.event_objects= { objclass.__name__ : [primary_id] }
- self.message=objclass.__name__
+ self.event_objects = {objclass.__name__ : [primary_id]}
+ self.message = objclass.__name__
if secondary_key in objs[0]:
self.message += " %s "%objs[0][secondary_key]
else:
return value
# attach it
- setattr (set_class,"call",set_call)
+ setattr(set_class, "call", set_call)
# define in module
- setattr(module,get_name,get_class)
- setattr(module,set_name,set_class)
+ setattr(module, get_name, get_class)
+ setattr(module, set_name, set_class)
# add in <module>.methods
try:
- methods=getattr(module,'methods')
- except:
- methods=[]
- methods += [get_name,set_name]
- setattr(module,'methods',methods)
+ methods = getattr(module, 'methods')
+ except Exception:
+ methods = []
+ methods += [get_name, set_name]
+ setattr(module, 'methods', methods)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-import xmlrpc.client
-from types import *
+#import xmlrpc.client
import textwrap
-import os
import time
import pprint
from PLC.Faults import *
from PLC.Parameter import Parameter, Mixed, python_type, xmlrpc_type
from PLC.Auth import Auth
-from PLC.Debug import profile
+#from PLC.Debug import profile
from PLC.Events import Event, Events
from PLC.Nodes import Node, Nodes
from PLC.Persons import Person, Persons
# we inherit object because we use new-style classes for legacy methods
-class Method (object):
+class Method:
"""
Base class for all PLCAPI functions. At a minimum, all PLCAPI
functions must define:
return True
- def __init__(self, api,caller=None):
+ def __init__(self, api, caller=None):
self.name = self.__class__.__name__
self.api = api
if caller:
# let a method call another one by propagating its caller
- self.caller=caller
+ self.caller = caller
else:
# Auth may set this to a Person instance (if an anonymous
# method, will remain None).
# legacy code cannot be type-checked, due to the way Method.args() works
# as of 5.0-rc16 we don't use skip_type_check anymore
- if not hasattr(self,"skip_type_check"):
+ if not hasattr(self, "skip_type_check"):
(min_args, max_args, defaults) = self.args()
# Check that the right number of arguments were passed in
continue
# what type of auth this is
if 'AuthMethod' in arg:
- auth_methods = ['session', 'password', 'capability', 'gpg', 'hmac','anonymous']
+ auth_methods = ['session', 'password', 'capability',
+ 'gpg', 'hmac', 'anonymous']
auth_method = arg['AuthMethod']
if auth_method in auth_methods:
event['auth_type'] = auth_method
elif isinstance(self.caller, Node):
event['node_id'] = self.caller['node_id']
- event.sync(commit = False)
+ event.sync(commit=False)
if hasattr(self, 'event_objects') and isinstance(self.event_objects, dict):
- for key in list(self.event_objects.keys()):
+ for key in self.event_objects.keys():
for object_id in self.event_objects[key]:
- event.add_object(key, object_id, commit = False)
+ event.add_object(key, object_id, commit=False)
# Set the message for this event
# Commit
event.sync()
- def help(self, indent = " "):
+ def help(self, indent=" "):
"""
Text documentation for the method.
"""
# Print parameter documentation right below type
if isinstance(param, Parameter):
- wrapper = textwrap.TextWrapper(width = 70,
- initial_indent = " " * param_offset,
- subsequent_indent = " " * param_offset)
+ wrapper = textwrap.TextWrapper(
+ width=70,
+ initial_indent=" " * param_offset,
+ subsequent_indent = " " * param_offset)
text += "\n".join(wrapper.wrap(param.doc)) + "\n"
param = param.type
# Integers and long integers are also special types. Accept
# either int or long types if an int or long is expected.
- elif expected_type in (IntType, LongType) and isinstance(value, (IntType, LongType)):
+ elif expected_type is int and isinstance(value, int):
pass
elif not isinstance(value, expected_type):
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
+# pylint: disable=c0103, c0111
+
+import subprocess
+import re
+from pprint import pformat
+from datetime import datetime as DateTimeType
import psycopg2
import psycopg2.extensions
# UNICODEARRAY not exported yet
psycopg2.extensions.register_type(psycopg2._psycopg.UNICODEARRAY)
-import types
-import traceback
-import subprocess
-import re
-from pprint import pformat
-
from PLC.Logger import logger
-from PLC.Debug import profile
+#from PLC.Debug import profile
from PLC.Faults import *
-from datetime import datetime as DateTimeType
class PostgreSQL:
def __init__(self, api):
# (Re)initialize database connection
try:
# Try UNIX socket first
- self.connection = psycopg2.connect(user = self.api.config.PLC_DB_USER,
- password = self.api.config.PLC_DB_PASSWORD,
- database = self.api.config.PLC_DB_NAME)
+ self.connection = psycopg2.connect(
+ user=self.api.config.PLC_DB_USER,
+ password=self.api.config.PLC_DB_PASSWORD,
+ database=self.api.config.PLC_DB_NAME)
except psycopg2.OperationalError:
# Fall back on TCP
- self.connection = psycopg2.connect(user = self.api.config.PLC_DB_USER,
- password = self.api.config.PLC_DB_PASSWORD,
- database = self.api.config.PLC_DB_NAME,
- host = self.api.config.PLC_DB_HOST,
- port = self.api.config.PLC_DB_PORT)
+ self.connection = psycopg2.connect(
+ user=self.api.config.PLC_DB_USER,
+ password=self.api.config.PLC_DB_PASSWORD,
+ database=self.api.config.PLC_DB_NAME,
+ host=self.api.config.PLC_DB_HOST,
+ port=self.api.config.PLC_DB_PORT)
self.connection.set_client_encoding("UNICODE")
(self.rowcount, self.description, self.lastrowid) = \
if isinstance(x, DateTimeType):
x = str(x)
elif isinstance(x, str):
- x = x.encode( 'utf-8' )
+ x = x.encode('utf-8')
if isinstance(x, bytes):
x = "'%s'" % str(x).replace("\\", "\\\\").replace("'", "''")
elif x is None:
x = 'NULL'
elif isinstance(x, (list, tuple, set)):
- x = 'ARRAY[%s]' % ', '.join([str(_quote(x)) for x in x])
+ x = 'ARRAY[%s]' % ', '.join([str(PostgreSQL._quote(x)) for x in x])
elif hasattr(x, '__pg_repr__'):
x = x.__pg_repr__()
else:
"""
Returns quoted version of the specified value.
"""
- return PostgreSQL._quote (value)
+ return PostgreSQL._quote(value)
# following is an unsuccessful attempt to re-use lib code as much as possible
# def quote(self, value):
# return adapt (value)
@classmethod
- def param(self, name, value):
+ def param(cls, name, value):
# None is converted to the unquoted string NULL
if isinstance(value, type(None)):
conversion = "s"
def rollback(self):
self.connection.rollback()
- def do(self, query, params = None):
+ def do(self, query, params=None):
cursor = self.execute(query, params)
cursor.close()
return self.rowcount
def next_id(self, table_name, primary_key):
- sequence = "%(table_name)s_%(primary_key)s_seq" % locals()
- sql = "SELECT nextval('%(sequence)s')" % locals()
- rows = self.selectall(sql, hashref = False)
+ sequence = "{}_{}_seq".format(table_name, primary_key)
+ sql = "SELECT nextval('{}')".format(sequence)
+ rows = self.selectall(sql, hashref=False)
if rows:
return rows[0][0]
-
return None
def last_insert_id(self, table_name, primary_key):
if isinstance(self.lastrowid, int):
sql = "SELECT %s FROM %s WHERE oid = %d" % \
(primary_key, table_name, self.lastrowid)
- rows = self.selectall(sql, hashref = False)
+ rows = self.selectall(sql, hashref=False)
if rows:
return rows[0][0]
# see http://www.python.org/dev/peps/pep-0249/
# accepts either None, a single dict, a tuple of single dict - in which case it execute's
# or a tuple of several dicts, in which case it executemany's
- def execute(self, query, params = None):
+ def execute(self, query, params=None):
cursor = self.cursor()
try:
if psycopg2:
query = re.sub(r'(%\([^)]*\)|%)[df]', r'\1s', query)
# rewrite wildcards set by Filter.py as '***' into '%'
- query = query.replace ('***','%')
+ query = query.replace('***', '%')
if not params:
if self.debug:
logger.debug('execute-dict: params {} query {}'
.format(params, query%params))
cursor.execute(query, params)
- elif isinstance(params,tuple) and len(params)==1:
+ elif isinstance(params, tuple) and len(params) == 1:
if self.debug:
logger.debug('execute-tuple {}'.format(query%params[0]))
- cursor.execute(query,params[0])
+ cursor.execute(query, params[0])
else:
- param_seq=(params,)
+ param_seq = (params,)
if self.debug:
for params in param_seq:
logger.debug('executemany {}'.format(query%params))
return cursor
- def selectall(self, query, params = None, hashref = True, key_field = None):
+ def selectall(self, query, params=None, hashref=True, key_field=None):
"""
Return each row as a dictionary keyed on field name (like DBI
selectrow_hashref()). If key_field is specified, return rows
if key_field is not None and key_field in labels:
# Return rows as a dictionary keyed on the specified field
# (like DBI selectall_hashref()).
- return dict([(row[key_field], row) for row in rows])
+ return {row[key_field]: row for row in rows}
else:
return rows
- def fields(self, table, notnull = None, hasdef = None):
+ def fields(self, table, notnull=None, hasdef=None):
"""
Return the names of the fields of the specified table.
"""
if hasdef is not None:
sql += " AND atthasdef is %(hasdef)s"
- rows = self.selectall(sql, locals(), hashref = False)
+ rows = self.selectall(sql, locals(), hashref=False)
self.fields_cache[(table, notnull, hasdef)] = [row[0] for row in rows]