From e787b2b0f09d9b56cdf483e9fccfb318f1bdd2f3 Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Fri, 15 Sep 2006 20:31:06 +0000 Subject: [PATCH] Initial checkin of new API implementation --- PLC/Methods/AdmAddNodeNetwork.py | 76 +++++++++++++++++++ PLC/Methods/AdmDeleteNodeNetwork.py | 59 ++++++++++++++ .../AdmGetAllNodeNetworkBandwidthLimits.py | 29 +++++++ PLC/Methods/AdmGetAllNodeNetworks.py | 43 +++++++++++ PLC/Methods/AdmGetSitePersons.py | 46 +++++++++++ PLC/Methods/AdmUpdateNodeNetwork.py | 75 ++++++++++++++++++ PLC/Methods/AdmUpdateSite.py | 76 +++++++++++++++++++ 7 files changed, 404 insertions(+) create mode 100644 PLC/Methods/AdmAddNodeNetwork.py create mode 100644 PLC/Methods/AdmDeleteNodeNetwork.py create mode 100644 PLC/Methods/AdmGetAllNodeNetworkBandwidthLimits.py create mode 100644 PLC/Methods/AdmGetAllNodeNetworks.py create mode 100644 PLC/Methods/AdmGetSitePersons.py create mode 100644 PLC/Methods/AdmUpdateNodeNetwork.py create mode 100644 PLC/Methods/AdmUpdateSite.py diff --git a/PLC/Methods/AdmAddNodeNetwork.py b/PLC/Methods/AdmAddNodeNetwork.py new file mode 100644 index 00000000..037d54a3 --- /dev/null +++ b/PLC/Methods/AdmAddNodeNetwork.py @@ -0,0 +1,76 @@ +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Nodes import Node, Nodes +from PLC.NodeNetworks import NodeNetwork, NodeNetworks +from PLC.Sites import Site, Sites +from PLC.Auth import PasswordAuth + +class AdmAddNodeNetwork(Method): + """ + Adds a new newtwork for a node. Any values specified in optional_vals are used, + otherwise defaults are used. Acceptable values for method are dhcp, static, + proxy, tap, and ipmi. Acceptable value for type is ipv4. If type is static, + the parameter optional_vals must be present and ip, gateway, network, broadcast, + netmask, and dns1 must all be specified. If type is dhcp, these parameters, even + if specified, are ignored. Returns the new nodenetwork_id (>0) if successful. + + PIs and techs may only add networks to their own nodes. Admins may + add networks to any node. + + Returns the new nodenetwork_id (> 0) if successful, faults otherwise. + """ + + roles = ['admin', 'pi', 'tech'] + + cant_update = lambda (field, value): field not in \ + ['nodenetwork_id'] + update_fields = dict(filter(cant_update, NodeNetwork.all_fields.items())) + + accepts = [ + PasswordAuth(), + NodeNetwork.all_fields['node_id'], + NodeNetwork.all_fields['method'], + NodeNetwork.all_fields['type'], + update_fields + ] + + returns = Parameter(int, '1 if successful') + + def call(self, auth, node_id, method, type, optional_vals = {}): + if filter(lambda field: field not in self.update_fields, optional_vals): + raise PLCInvalidArgument, "Invalid fields specified" + + # check if node exists + nodes = Nodes(self.api, [node_id], Node.extra_fields).values() + if not nodes: + raise PLCInvalidArgument, "No such node" + node = nodes[0] + + # Make sure node network doesnt already exist + nodenetworks = NodeNetworks(self.api).values() + if nodenetworks: + for nodenetwork in nodenetworks: + if nodenetwork['node_id'] == node_id and nodenetwork['method'] == method and nodenetwork['type'] == type: + raise PLCInvalidArgument, "Node Network already exists" + + # Authenticated function + assert self.caller is not None + + # If we are not an admin, make sure that the caller is a + # member of the site where the node exists. + if 'admin' not in self.caller['roles']: + if node['site_id'] not in self.caller['site_ids']: + raise PLCPermissionDenied, "Not allowed to add node network for specified node" + if 'tech' not in self.caller['roles']: + raise PLCPermissionDenied, "Not allowed to add node network for specified node" + + + # add node network + nodenetwork = NodeNetwork(self.api, optional_vals) + nodenetwork['node_id'] = node_id + nodenetwork['method'] = method + nodenetwork['type'] = type + nodenetwork.flush() + + return nodenetwork['nodenetwork_id'] diff --git a/PLC/Methods/AdmDeleteNodeNetwork.py b/PLC/Methods/AdmDeleteNodeNetwork.py new file mode 100644 index 00000000..a2e8005e --- /dev/null +++ b/PLC/Methods/AdmDeleteNodeNetwork.py @@ -0,0 +1,59 @@ +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Auth import PasswordAuth +from PLC.Nodes import Node, Nodes +from PLC.NodeNetworks import NodeNetwork, NodeNetworks + +class AdmDeleteNodeNetwork(Method): + """ + Delete an existing Node Network. Nodenetwork_id must be associated to + node_id and not be associated with a different node. + + Admins may delete any node network. PIs and techs can only delete + nodenetworks for thier nodes. + + Returns 1 if successful, faults otherwise. + """ + + roles = ['admin', 'pi', 'tech'] + + accepts = [ + PasswordAuth(), + Mixed(NodeNetwork.all_fields['node_id'], + NodeNetwork.all_fields['hostname']), + Mixed(NodeNetwork.all_fields['nodenetwork_id'], + NodeNetwork.all_fields['hostname']) + ] + + returns = Parameter(int, '1 if successful') + + def call(self, auth, node_id_or_hostname, nodenetwork_id_or_hostname): + # Get node network information + nodenetworks = NodeNetworks(self.api, [nodenetwork_id_or_hostname]).values() + if not nodenetworks: + raise PLCInvalidArgument, "No such node network" + nodenetwork = nodenetworks[0] + + # Get node information + nodes = Nodes(self.api, [node_id_or_hostname]).values() + if not nodes: + raise PLCInvalidArgument, "No such node" + node = nodes[0] + + # Check if node network is associated with specified node + if not node['node_id'] == nodenetwork['node_id'] or nodenetwork['nodenetwork_id'] not in node['nodenetwork_ids']: + raise PLCInvalidArgument, "node network not assoicated with this node" + + assert self.caller is not None + + # If we are not an admin, make sure that the caller is a + # member of the site at which the node is located. + if 'admin' not in self.caller['roles']: + if node['site_id'] not in self.caller['site_ids']: + raise PLCPermissionDenied, "Not allowed to delete node network at this node" + if 'tech' not in self.caller['roles']: + raise PLCPermissionDenied, "Not allowed to add node network for specified node" + nodenetwork.delete() + + return 1 diff --git a/PLC/Methods/AdmGetAllNodeNetworkBandwidthLimits.py b/PLC/Methods/AdmGetAllNodeNetworkBandwidthLimits.py new file mode 100644 index 00000000..463d9a3e --- /dev/null +++ b/PLC/Methods/AdmGetAllNodeNetworkBandwidthLimits.py @@ -0,0 +1,29 @@ +import os + +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.NodeNetworks import NodeNetwork, NodeNetworks +from PLC.Auth import PasswordAuth + +class AdmGetAllNodeNetworkBandwidthLimits(Method): + """ + Returns an array of all the valid bandwith limits for node networks. + + """ + + roles = ['admin', 'pi', 'user', 'tech'] + + accepts = [ + PasswordAuth() + ] + + returns = [NodeNetwork.fields['bwlimit']] + + def call(self, auth): + # Authenticated function + assert self.caller is not None + + nodenetwork_bwlimits = NodeNetwork.bwlimits + + return nodenetwork_bwlimits diff --git a/PLC/Methods/AdmGetAllNodeNetworks.py b/PLC/Methods/AdmGetAllNodeNetworks.py new file mode 100644 index 00000000..a1fd3a84 --- /dev/null +++ b/PLC/Methods/AdmGetAllNodeNetworks.py @@ -0,0 +1,43 @@ +import os + +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.NodeNetworks import NodeNetwork, NodeNetworks +from PLC.Nodes import Node, Nodes +from PLC.Auth import PasswordAuth + +class AdmGetAllNodeNetworks(Method): + """ + Returns all the networks this node is connected to, as an array of + structs. + + """ + + roles = ['admin', 'pi', 'user', 'tech'] + + accepts = [ + PasswordAuth(), + Mixed(Node.fields['node_id'], + Node.fields['hostname']) + ] + + returns = [NodeNetwork.all_fields] + + def call(self, auth, node_id_or_hostname): + # Authenticated function + assert self.caller is not None + + # Get node information + nodes = Nodes(self.api, [node_id_or_hostname], NodeNetwork.all_fields).values() + if not nodes: + raise PLCInvalidArgument, "No such node" + node = nodes[0] + + # Get node networks for this node + nodenetwork_ids = node['nodenetwork_ids'] + if not nodenetwork_ids: + raise PLCInvalidArgument, "Node has no node networks" + nodenetworks = NodeNetworks(self.api, nodenetwork_ids).values() + + return nodenetworks diff --git a/PLC/Methods/AdmGetSitePersons.py b/PLC/Methods/AdmGetSitePersons.py new file mode 100644 index 00000000..0839bc68 --- /dev/null +++ b/PLC/Methods/AdmGetSitePersons.py @@ -0,0 +1,46 @@ +import os + +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Sites import Site, Sites +from PLC.Auth import PasswordAuth + +class AdmGetSitePersons(Method): + """ + Return a list of person_ids for the site specified. + + Admins may retrieve person_ids at any site by not specifying + site_id_or_name or by specifying an empty list. PIs may only retrieve + the person_ids at their site + + """ + + roles = ['admin', 'pi'] + + accepts = [ + PasswordAuth(), + Site.fields['site_id'] + ] + + returns = [Site.all_fields['person_ids']] + + def call(self, auth, site_id): + # Authenticated function + assert self.caller is not None + + # Get site information + sites = Sites(self.api, [site_id], ['person_ids']).values() + + # make sure sites are found + if not sites: + raise PLCInvalidArgument, "No such site" + site = sites[0] + if 'admin' not in self.caller['roles']: + if site['site_id'] not in self.caller['site_ids']: + raise PLCPermissionDenied, "Not allowed to update node network" + if 'pi' not in self.caller['roles']: + raise PLCPermissionDenied, "User account not allowed to update node network" + person_ids = site['person_ids'] + + return person_ids diff --git a/PLC/Methods/AdmUpdateNodeNetwork.py b/PLC/Methods/AdmUpdateNodeNetwork.py new file mode 100644 index 00000000..22d57f41 --- /dev/null +++ b/PLC/Methods/AdmUpdateNodeNetwork.py @@ -0,0 +1,75 @@ + +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Nodes import Node, Nodes +from PLC.NodeNetworks import NodeNetwork, NodeNetworks +from PLC.Auth import PasswordAuth + +class AdmUpdateNodeNetwork(Method): + """ + Updates an existing node network. Any values specified in optional_vals + are used, otherwise defaults are used. Acceptable values for method are + dhcp and static. If type is static, the parameter optional_vals must + be present and ip, gateway, network, broadcast, netmask, and dns1 must + all be specified. If type is dhcp, these parameters, even if + specified, are ignored. + + PIs and techs may only add networks to their own nodes. Admins may + add networks to any node. + + Returns 1 if successful, faults otherwise. + """ + + roles = ['admin', 'pi', 'tech'] + + cant_update = lambda (field, value): field not in \ + ['nodenetwork_id'] + update_fields = dict(filter(cant_update, NodeNetwork.all_fields.items())) + + accepts = [ + PasswordAuth(), + Mixed(NodeNetwork.fields['nodenetwork_id'], + NodeNetwork.fields['hostname']), + update_fields + ] + + returns = Parameter(int, '1 if successful') + + def call(self, auth, nodenetwork_id_or_hostname, optional_vals=None): + if filter(lambda field: field not in self.update_fields, optional_vals): + raise PLCInvalidArgument, "Invalid fields specified" + + # Authenticated function + assert self.caller is not None + + # Get nodenetwork information + nodenetworks = NodeNetworks(self.api, [nodenetwork_id_or_hostname]).values() + if not nodenetworks: + raise PLCInvalidArgument, "No such node network" + nodenetwork = nodenetworks[0] + + # Get Node using this node network + #nodes = Nodes(self.api, [nodenetwork['node_id']]).values() + #if not nodes: + # raise PLCPermissionDenied, "Node network is not associated with a node" + #node = nodes[0] + + + # If we are not an admin, make sure that the caller is a + # member of the site where the node exists. + if 'admin' not in self.caller['roles']: + nodes = Nodes(self.api, [nodenetwork['node_id']]).values() + if not nodes: + raise PLCPermissionDenied, "Node network is not associated with a node" + node = nodes[0] + if node['site_id'] not in self.caller['site_ids']: + raise PLCPermissionDenied, "Not allowed to update node network" + if 'tech' not in self.caller['roles']: + raise PLCPermissionDenied, "User account not allowed to update node network" + + # Update node network + nodenetwork.update(optional_vals) + nodenetwork.flush() + + return 1 diff --git a/PLC/Methods/AdmUpdateSite.py b/PLC/Methods/AdmUpdateSite.py new file mode 100644 index 00000000..b17fcc7a --- /dev/null +++ b/PLC/Methods/AdmUpdateSite.py @@ -0,0 +1,76 @@ +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Sites import Site, Sites +from PLC.Auth import PasswordAuth + +class AdmUpdateSite(Method): + """ + Updates a site. Only the fields specified in update_fields are + updated, all other fields are left untouched. + + To remove a value without setting a new one in its place (for + example, to remove an address from the node), specify -1 for int + and double fields and 'null' for string fields. hostname and + boot_state cannot be unset. + + PIs can only update sites they are a member of. Only admins can + update max_slices. + + Returns 1 if successful, faults otherwise. + """ + + roles = ['admin', 'pi', 'tech'] + + cant_update = lambda (field, value): field not in \ + ['site_id', 'nodegroup_id', 'organization_id', 'ext_consortium_id', 'date_created'] + update_fields = dict(filter(cant_update, Site.all_fields.items())) + + accepts = [ + PasswordAuth(), + Mixed(Site.fields['site_id'], + Site.fields['abbreviated_name']), + update_fields + ] + + returns = Parameter(int, '1 if successful') + + def call(self, auth, site_id_or_abbrev_name, update_fields): + # Only admin can update max_slices + #if 'admin' not in self.caller['roles']: + # if update_fields.has_key('max_slices '): + # raise PLCInvalidArgument, "Only admins can update max_slices" + + # Check for invalid fields + if filter(lambda field: field not in self.update_fields, update_fields): + raise PLCInvalidArgument, "Invalid field specified" + + # XML-RPC cannot marshal None, so we need special values to + # represent "unset". + for key, value in update_fields.iteritems(): + if value == -1 or value == "null": + if key in ['name', 'abbreviated_name', 'login_base', 'is_public', 'max_slices']: + raise PLCInvalidArgument, "%s cannot be unset" % key + update_fields[key] = None + + # Get site information + sites = Sites(self.api, [site_id_or_abbrev_name], Site.all_fields) + if not sites : + raise PLCInvalidArgument, "No such site" + + site = sites.values()[0] + + # If we are not an admin, make sure that the caller is a + # member of the site at which the node is located. + if 'admin' not in self.caller['roles']: + if site['site_id'] not in self.caller['site_ids']: + raise PLCPermissionDenied, "Not allowed to modify specified site" + if 'tech' not in self.caller['roles']: + raise PLCPermissionDenied, "Not allowed to add node network for specified node" + + + site.update(update_fields) + site.flush() + + return 1 + -- 2.47.0