Esempio n. 1
0
File: lvm.py Progetto: mattmb/spoke
    def create(self, lv_name, lv_size):
        """Create logical volume; return True"""
        lv_size = str(lv_size) + self.lv_units
        lv_name = common.validate_hostname(
            lv_name)  # LV names are always hostnames
        lv_size = common.validate_storage_format(lv_size)

        args = ['lvcreate', '-n', lv_name, '-L', lv_size, self.vg_name]
        str_args = " ".join(args)
        msg = "Running " + str_args
        self.log.debug(msg)
        try:
            result = subprocess.Popen(args,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      close_fds=True)
        except Exception:
            msg = 'Running command %s failed' % str_args
            #            trace = traceback.format_exec()
            raise error.SpokeError(msg)

        data = result.communicate()
        stdout = data[0]
        stderr = data[1]
        msg = "Command stdout was: %s, stderr was: %s" % (stdout, stderr)
        self.log.debug(msg)

        # Errors we know about
        if "Volume group \"%s\" not found" % self.vg_name in stderr:
            msg = "volume group '%s' was not found." % self.vg_name
            raise error.NotFound(msg)
        elif "Insufficient free extents" in stderr:
            msg = "Not enough free space to create LV"
            raise error.InsufficientResource(msg)
        elif "Logical volume \"%s\" already exists in volume group \"%s\"" % (
                lv_name, self.vg_name) in stderr:
            msg = "Logical volume '%s' already exists in volume group '%s'" % (
                lv_name, self.vg_name)
            raise error.AlreadyExists(msg)
        # Catch unexpected errors
        if result.returncode != 0:
            msg = "Create command returned non-zero: %s stdout was: %s, stderr was: %s" % \
                                                        (result.returncode, stdout, stderr)
            raise error.LVMError(msg)

        result = self.get(lv_name)
        if result['exit_code'] == 0 and result['count'] == 1:
            result['msg'] = "Created %s:" % result['type']
            return result
        else:
            msg = 'Create operation returned OK, but unable to find object'
            raise error.NotFound(msg)
        self.log.debug('Result: %s' % result)
        return result
Esempio n. 2
0
 def _delete_object(self, dn, dn_info=None):
     """Delete an LDAP object (e.g. a dn or attribute)."""
     operation = {
         'del_dn': self.LDAP.delete_s,
         'del_attr': self.LDAP.modify_s
     }
     filter = 'objectClass=*'
     if dn_info == None:
         del_type = 'del_dn'  # We're deleting a dn
         kargs = {'dn': dn}
         attrlist = None
     else:
         del_type = 'del_attr'  # We're deleting an attribute
         kargs = {'dn': dn, 'modlist': dn_info}
         attrlist = []  # Collect a list of attributes to return
         for item in dn_info:
             attrlist.append(item[1])
         #if len(dn_info) == 1: # Try and construct a filter
         #    filter = '%s=%s' % (dn_info[0][1], dn_info[0][2])
     #self.log.debug('Running with filter %s' % filter)
     try:
         operation[del_type](**kargs)
     except ldap.NO_SUCH_OBJECT, e:
         msg = '%s does not exist, cannot delete' % dn
         raise error.NotFound(msg)
Esempio n. 3
0
File: ca.py Progetto: mattmb/spoke
 def delete(self):
     """Delete a CA's file structure and configuration files."""
     # NB This will fail if you've been storing certs or reqs
     if self.get()['data'] == []:
         msg = '%s does not exist, cannot delete' % self.ca_name
         raise error.NotFound(msg)
     self.req_files.append(self.ca_req_file)
     for req_file in self.req_files:
         if (os.path.exists(req_file)):
             os.remove(req_file)
     self.req_dirs.sort(reverse=True)
     for directory in self.req_dirs:
         if (os.path.exists(directory)):
             try:
                 os.removedirs(directory)
             except Exception as e:
                 msg = 'Unable to delete directory %s: %s' % (directory, e)
                 self.log.debug(msg)
     result = self.get()
     if result['exit_code'] == 3 and result['count'] == 0:
         result['msg'] = "Deleted %s:" % result['type']
         return result
     else:
         msg = 'Delete operation returned OK, but object still there?'
         raise error.ValidationError(msg)
Esempio n. 4
0
File: ip.py Progetto: mattmb/spoke
    def create(self, aloc_ips=None):
        """Create subnet kv stores; populate with IPs; return True."""
        if not (self.network and self.mask):
            msg = 'Please specify ip and mask'
            raise error.InputError(msg)

        if self.KV.exists(self.kv_aloc) or self.KV.exists(self.kv_free):
            msg = 'Subnet %s/%s already exists' % (self.kv_name, str(
                self.mask))
            raise error.AlreadyExists(msg)

        self._populate_aloc_ips(aloc_ips)
        self._populate_free_ips()

        msg = 'Created subnet %s/%s with %s free and %s reserved IPs' \
        % (self.kv_name, str(self.mask), len(self.free_ips), len(self.aloc_ips))
        self.log.debug(msg)
        result = self.get()
        if result['exit_code'] == 0 and result['count'] == 1:
            result['msg'] = "Created %s:" % result['type']
            return result
        else:
            msg = 'Create operation returned OK, but unable to find object'
            raise error.NotFound(msg)
        return result
Esempio n. 5
0
 def create(self):
     """Create a DNS zone; return a DNS zone object."""
     filter = '(%s:dn:=%s)' % (self.dns_zone_name_attr, self.domain_name)
     dn = self.zone_dn
     dn_attr = {
         'objectClass': ['top', self.dns_zone_class],
         'relativeDomainName': ['@'],
         'zoneName': [self.domain_name]
     }
     dn_info = [(k, v) for (k, v) in dn_attr.items()]
     self.log.debug('Adding DNS zone: ' + dn)
     try:
         result = self._create_object(dn, dn_info)
     except error.NotFound:
         # Let's see if it's just the dns container missing.
         child_dn = '%s=%s,%s' % (self.dns_cont_attr, self.dns_cont_name, \
                                                             self.org_dn)
         child_dn_attr = {
             'objectClass': ['top', self.dns_cont_class],
             self.dns_cont_attr: [self.dns_cont_name]
         }
         child_dn_info = [(k, v) for (k, v) in child_dn_attr.items()]
         try:
             self._create_object(child_dn, child_dn_info)
         except error.NotFound:
             # Not it wasn't just the dns container
             msg = "Part of %s missing, can't create." % dn
             raise error.NotFound(msg)
         # And then try the original create zone again.
         result = self._create_object(dn, dn_info)
     self.log.debug('Result: %s' % result)
     return result
Esempio n. 6
0
 def _create_object(self, dn, dn_info):
     """Create a new LDAP object (e.g. a dn or attribute)."""
     # Allowed LDAP operations
     operation = {'add':self.LDAP.add_s, 'mod':self.LDAP.modify_s}
     try:
         int(dn_info[0][0]) #attribute mod opertations begin with an integer.
         type = 'mod'
         attrlist = [] # Collect a list of attributes to return
         for item in dn_info:
             attrlist.append(item[1])
     except:
         type = 'add' #if it's not a modification, it's an add operation.
         attrlist = None
     
     try:
         operation[type](dn, dn_info)
     except ldap.ALREADY_EXISTS:
         msg = 'Entry %s already exists.' % dn
         raise error.AlreadyExists(msg)
     except ldap.TYPE_OR_VALUE_EXISTS:
         msg = 'Attempt to add attribute to %s which already exists.' % dn
         raise error.AlreadyExists(msg)
     except ldap.CONSTRAINT_VIOLATION:
         msg = 'Attribute already exists and does not support multiples'
         raise error.AlreadyExists(msg)
     except ldap.NO_SUCH_OBJECT:
         msg = "Part of %s missing, can't create." % dn
         raise error.NotFound(msg)
     except ldap.LDAPError, e:
         trace = traceback.format_exc()
         raise error.SpokeLDAPError(e, trace)
Esempio n. 7
0
 def modify(self, vm_power_state):
     '''Change the power state of a vm'''
     if vm_power_state == "on":
         result = self.create()
     elif vm_power_state == "off":
         result = self.delete()
     elif vm_power_state == "reboot":
         try:
             result = self.dom.reboot(0)
             msg = "Power cycled %s" % self.vm_name
             self.log.debug(msg)
         except libvirt.libvirtError:
             msg = "Failed to power cycle %s" % self.vm_name
             raise error.LibvirtError(msg)
         if result != 0:
             msg = 'Unknown error rebooting VM, libvirt returned %s' % result
             raise error.LibvirtError(msg)
     elif vm_power_state == "forceoff":
         result = self.delete(force=True)
     else:
         msg = "Invalid state, must be one of: on|off|reboot|forceoff"
         raise error.InputError, msg
     #self.conn.close()
     result = self.get()
     if result['exit_code'] == 0 and result['count'] == 1:
         result['msg'] = "Modified %s:" % result['type']
         return result
     else:
         msg = 'Power operation returned OK, but unable to find object'
         raise error.NotFound(msg)
     return result
Esempio n. 8
0
 def __init__(self, hv_uri, vm_name):
     '''Get some basic config and connect to hypervisor'''
     SpokeVMPower.__init__(self, vm_name)
     self.hv_uri = hv_uri
     self.vm_name = common.validate_hostname(vm_name)
     self.conn = None
     try:
         self.conn = libvirt.open(self.hv_uri)
         msg = "Successfully connected to: " + self.hv_uri
         self.log.debug(msg)
     except libvirt.libvirtError:
         trace = traceback.format_exc()
         msg = 'Libvirt connection to URI %s failed' % self.hv_uri
         raise error.LibvirtError(msg, trace)
     except Exception:
         trace = traceback.format_exc()
         msg = 'Unknown error'
         raise error.SpokeError(msg, trace)
     finally:
         if self.conn == None:
             msg = 'Libvirt connection to URI %s failed' % self.hv_uri
             raise error.LibvirtError(msg)
         try:
             self.dom = self.conn.lookupByName(self.vm_name)
         except libvirt.libvirtError:
             msg = "VM %s not found." % self.vm_name
             raise error.NotFound(msg)
Esempio n. 9
0
File: vcs.py Progetto: mattmb/spoke
 def create(self, repo):
     """Enable user access to a repository; return repository info."""
     repo = self._validate_input(repo)
     filter = '%s=%s' % (self.svn_repo_attr, repo)
     scope = self.search_scope
     dn = self.user_dn
     dn_info = []
     try:
         if repo in self.user_attrs[self.svn_repo_attr]:
             msg = 'Repository %s already enabled for user %s.' % \
                                                     (repo, self.user_dn)
             raise error.AlreadyExists(msg)
         else:
             msg = 'Repository %s not found, creating...' % repo
             raise error.NotFound(msg)
     except (KeyError, error.NotFound):
         if not self.svn_class in self.user_classes:
             # This is our first repository, so add class and enable.
             dn_info.append((0, 'objectClass', self.svn_class))
             dn_info.append((0, self.svn_enable_attr, 'TRUE'))
         dn_info.append((0, self.svn_repo_attr, repo))
         self.log.debug('Adding %s to %s ' % (dn_info, dn))
         result = self._create_object(dn, dn_info)
         self.log.debug('Result: %s' % result)
     return result
Esempio n. 10
0
File: ca.py Progetto: mattmb/spoke
 def _get_ca(self, ca_name):
     ca_name = common.is_shell_safe(ca_name)
     ca = SpokeCA(ca_name)
     if not ca.get()['data']:
         msg = "Can't find CA %s" % ca_name
         raise error.NotFound(msg)
     return ca
Esempio n. 11
0
 def modify(self, org_name, suffix):
     """Modify an org's default suffix; return True."""
     org_info = self.get(org_name)['data']
     if org_info == []:
         msg = 'Unable to modify org suffix, no org found.'
         self.log.error(msg)
         raise error.NotFound(msg)
     dn = org_info[0].__getitem__(0)
     old_result = org_info[0].__getitem__(1)
     old_classes = old_result['objectClass']
     
     try:
         old_attrs = {self.org_suffix_attr:old_result[self.org_suffix_attr]}    
     except KeyError: # suffix has not been set.
         old_attrs = {self.org_suffix_attr: ''}
         #new_attrs = {'objectClass': [self.user_class] }
                      #self.org_suffix_attr: suffix}
     new_attrs = {self.org_suffix_attr: suffix}
     if not self.user_class in old_classes:
         new_attrs['objectClass'] = self.user_class
     if new_attrs == old_attrs:
         msg = 'New suffix is equal to old suffix, nothing to update.'
         self.log.debug(msg)
         return True
     self._modify_attributes(dn, new_attrs, old_attrs)
Esempio n. 12
0
 def _get_dhcp_group(self, dhcp_server, group_name):
     """Retrieve a DHCP group object."""
     group = SpokeDHCPGroup(dhcp_server)
     result = group.get(group_name)
     if result['data'] == []:
         msg = "Can't find DHCP group for %s" % dhcp_server
         raise error.NotFound(msg)
     return result
Esempio n. 13
0
 def _get_user(self, org_name, user_id):
     """Retrieve a user object."""
     user = SpokeUser(org_name)
     result = user.get(user_id, unique=True)
     if result['data'] == []:
         msg = "Can't find user %s in org %s" % (user_id, org_name)
         raise error.NotFound(msg)
     return result
Esempio n. 14
0
 def _get_org(self, org_name):
     """Retrieve our org object."""
     org = SpokeOrg()
     result = org.get(org_name)
     if result['data'] == []:
         msg = "Can't find org %s" % org_name
         raise error.NotFound(msg)
     return result
Esempio n. 15
0
 def _get_list(self, org_name, list_address):
     list = SpokeMailingList(org_name)
     result = list.get(list_address)
     if result['data'] == []:
         msg = "Can't find mailing list %s in %s" % (list_address, org_name)
         self.log.error(msg)
         raise error.NotFound(msg)
     return result
Esempio n. 16
0
File: lvm.py Progetto: mattmb/spoke
    def delete(self, lv_name):
        """Delete logical volume; return True."""
        lv_name = common.validate_hostname(
            lv_name)  # LV names are always hostnames

        args = ['lvremove', '-f', '%s/%s' % (self.vg_name, lv_name)]
        str_args = " ".join(args)
        msg = "Running " + str_args
        self.log.debug(msg)
        try:
            result = subprocess.Popen(args,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      close_fds=True)
        except Exception:
            msg = 'Running command %s failed' % str_args
            #trace = traceback.format_exec()
            raise error.SpokeError(msg)

        data = result.communicate()
        stdout = data[0]
        stderr = data[1]
        msg = "Command stdout was: %s, stderr was: %s" % (stdout, stderr)
        self.log.debug(msg)

        if "Volume group \"%s\" not found" % self.vg_name in stderr:
            msg = "volume group '%s' was not found." % self.vg_name
            raise error.NotFound(msg)
        elif "logical volume(s) not found" in stderr:
            msg = "logical volume '%s' not found." % lv_name
            raise error.NotFound(msg)

        # Catch non-specific errors
        if result.returncode != 0:
            msg = "Delete command returned non-zero: %s stdout was: %s, stderr was: %s" % \
                                                        (result.returncode, stdout, stderr)
            raise error.LVMError(msg)

        result = self.get(lv_name)
        if result['exit_code'] == 3 and result['count'] == 0:
            result['msg'] = "Deleted %s:" % result['type']
            self.log.debug('Result: %s' % result)
            return result
        else:
            msg = 'Delete operation returned OK, but object still there?'
            raise error.SearchError(msg)
Esempio n. 17
0
 def _get_dhcp_service(self, dhcp_server):
     """Retrieve a DHCP service object."""
     service = SpokeDHCPService()
     result = service.get(dhcp_server)
     if result['data'] == []:
         msg = "Can't find DHCP service for %s" % dhcp_server
         raise error.NotFound(msg)
     return result
Esempio n. 18
0
File: ca.py Progetto: mattmb/spoke
 def _verify(self):
     """Verify a certificate request; return True (0) or False (1)"""
     try:
         req = X509.load_request(self.req_file)
     except:
         msg = 'Certificate request file %s not found' % self.req_file
         raise error.NotFound(msg)
     pkey = req.get_pubkey()
     return req.verify(pkey)
Esempio n. 19
0
 def _get_dhcp_host(self, dhcp_server, group_name, host_name):
     """Retrieve a DHCP host object."""
     host = SpokeDHCPHost(dhcp_server, group_name)
     result = host.get(host_name)
     if result['data'] == []:
         msg = "Can't find DHCP host for %s in group %s" % (dhcp_server, \
                                                                 group_name)
         raise error.NotFound(msg)
     return result
Esempio n. 20
0
 def _modify_attributes(self, dn, new_attrs, old_attrs=None):
     """Modify an LDAP object (e.g. a dn or attribute)."""
     ignore_old = 0
     if old_attrs==None:
         old_object = self._get_object(dn, ldap.SCOPE_BASE,
                                     '(objectClass=*)', unique=True)
         if old_object['data'] == []:
             msg = '%s does not exist, cannot modify' % dn
             raise error.NotFound(msg)
         old_attrs = old_object['data'][0][1]
         ignore_old = 1
         
     dn_info = ldap.modlist.modifyModlist(old_attrs, new_attrs, 
                                          ignore_oldexistent=ignore_old)   
     try:
         self.LDAP.modify_s(dn, dn_info)
     except ldap.NO_SUCH_ATTRIBUTE, e:
         msg = 'Attribute does not exist, cannot modify'
         raise error.NotFound(msg)
Esempio n. 21
0
 def delete(self):
     """Delete a user account's password; return True."""           
     dn_info = []
     dn = self.user_dn
     if not self.user_pwd_attr in self.user_attrs:
         msg = 'Password missing for user %s, cannot delete.' % self.user_id
         raise error.NotFound(msg)
     dn_info.append((ldap.MOD_DELETE, self.user_pwd_attr, None))
     self.log.debug('Deleting %s from user %s ' % (dn_info, dn))
     result = self._delete_object(dn, dn_info)
     result['msg'] = 'Password deleted for user %s' % self.user_id
     self.log.debug('Result: %s' % result)
     return result
Esempio n. 22
0
File: ca.py Progetto: mattmb/spoke
 def delete(self):
     """Delete a certificate and its associated key."""
     # NB This will fail if you've been storing certs or reqs
     for file in (self.key_file, self.cert_file):
         try:
             os.remove(file)
         except (OSError, IOError):
             msg = 'Unable to delete file %s' % file
             raise error.NotFound(msg)
     result = self.get()
     if result['exit_code'] == 3 and result['count'] == 0:
         result['msg'] = "Deleted %s:" % result['type']
         return result
     else:
         msg = 'Delete operation returned OK, but object still there?'
         raise error.ValidationError(msg)
Esempio n. 23
0
 def create(self):
     '''Power on a VM'''
     try:
         self.dom.create()
     except libvirt.libvirtError:
         msg = "VM %s is already powered on." % self.vm_name
         raise error.VMRunning, msg
     #self.conn.close()
     result = self.get()
     if result['exit_code'] == 0 and result['count'] == 1:
         result['msg'] = "Powered on %s:" % result['type']
         return result
     else:
         msg = 'Power operation returned OK, but unable to find object'
         raise error.NotFound(msg)
     return result
Esempio n. 24
0
File: ca.py Progetto: mattmb/spoke
 def create(self):
     """Create certificate request; return certificate request file."""
     try:
         pkey = self._gen_and_save_key(self.key_file)
     except IOError:
         msg = 'Failed to open key file: ' + self.key_file
         raise error.NotFound(msg)
     name = self._gen_x509_name(self.cn)
     req = X509.Request()
     req.set_version(3)
     req.set_pubkey(pkey)
     req.set_subject_name(name)
     req.sign(pkey, 'sha1')
     req.save(self.req_file)
     result = self.get()
     return result
Esempio n. 25
0
 def __init__(self, org_name):
     """Get config, setup logging and LDAP connection."""
     SpokeLDAP.__init__(self)
     self.config = config.setup()
     self.log = logging.getLogger(__name__)
     self.search_scope = 2 # ldap.SCOPE_SUBTREE
     self.retrieve_attr = None
     self.base_dn = self.config.get('LDAP', 'basedn')
     self.org_name = org_name
     self.org = self._get_org(self.org_name)
     if self.org['data'] == []:
         msg = 'Org %s not found: cannot delete children' % self.org_name
         raise error.NotFound(msg)
     self.org_dn = self.org['data'][0].__getitem__(0)
     self.container_attr = self.config.get('ATTR_MAP', 'container_attr', 'ou')
     self.container_class = self.config.get('ATTR_MAP', \
                                     'container_class', 'organizationalUnit')
Esempio n. 26
0
    def delete(self):
        """Delete UUID object; return True."""
        dn = self.next_uuid_dn
        dn_info = []
        if self.next_uuid_class in self.next_uuid_classes:
            dn_info.append((1, 'objectClass', self.next_uuid_class))
        if self.next_uuid_attr in self.next_uuid_attrs:
            dn_info.append((1, self.next_uuid_attr, None))

        if dn_info == []:
            msg = 'No UUID found, nothing to delete.'
            raise error.NotFound(msg)
        self.log.debug('Deleting %s from %s ' % (dn_info, dn))
        result = self._delete_object(dn, dn_info)
        result['msg'] = 'Deleted UUID:'
        self.log.debug('Result: %s' % result)
        return result
Esempio n. 27
0
File: tftp.py Progetto: mattmb/spoke
 def create(self, mac, template, run_id=None):
     """Creates a config at mac using template"""
     mac = common.validate_mac(mac)
     if run_id is not None:
         if not common.is_integer(run_id):
             msg = "Run ID must be an integer or not defined"
             raise error.InputError, msg
     mac = string.replace(mac, ":", "-")  #Format for use on tftp filesystem
     template = self._validate_template(template)
     template_path = self.tftp_dir + template
     template_file = open(template_path)
     dst = self.tftp_dir + self.tftp_prefix + mac
     #Check that at least one line has kernel arguments
     kernel_arg_lines = 0
     for line in template_file:
         if 'append' in line:
             kernel_arg_lines += 1
     if kernel_arg_lines < 1 and run_id is not None:
         msg = "No kernel arguments in specified template. Should be more than one line starting append."
         raise error.InputError, msg
     template_file.close
     template_file = open(template_path)
     #Check that nothing exists at that mac location before trying to make a file
     if not os.path.lexists(dst):
         mac_file = open(dst, 'w')
         #Loop file adding run_id at correct line
         for line in template_file:
             if 'append' in line and run_id:
                 #remove the line break and add run_id at end of kernel args
                 line = line.rstrip('\n')
                 mac_file.write(line + " run_id=" + str(run_id) + "\n")
             else:
                 mac_file.write(line)
         mac_file.close
     else:
         msg = "Config for mac %s already exists, can't create" % mac
         raise error.AlreadyExists, msg
     result = self.search(mac)
     if result['exit_code'] == 0 and result['count'] == 1:
         result['msg'] = "Created %s:" % result['type']
         return result
     else:
         msg = 'Create operation returned OK, but unable to find object'
         raise error.NotFound(msg)
     return result
Esempio n. 28
0
File: ca.py Progetto: mattmb/spoke
 def delete(self, delete_key=True):
     """Delete a certificate request; return True"""
     try:
         os.remove(self.req_file)
         if delete_key:
             os.remove(self.key_file)
     except (OSError, IOError):
         msg = 'Failed to delete request %s and/or key %s' \
                                         % (self.req_file, self.key_file)
         raise error.NotFound(msg)
     except Exception as e:
         raise e
     result = self.get()
     if result['exit_code'] == 3 and result['count'] == 0:
         result['msg'] = "Deleted %s:" % result['type']
         return result
     else:
         msg = 'Delete operation returned OK, but object still there?'
         raise error.ValidationError(msg)
Esempio n. 29
0
File: vcs.py Progetto: mattmb/spoke
    def delete(self, repo):
        """Disable user access to a repository; return True."""
        repo = self._validate_input(repo)
        filter = '%s=%s' % (self.svn_repo_attr, repo)
        dn = self.user_dn
        dn_info = []
        if self.svn_repo_attr in self.user_attrs:
            dn_info.append((1, self.svn_repo_attr, repo))
        if len(self.user_attrs) == 1:
            # This is the last repository, so we can delete the class also.
            dn_info.append((1, 'objectClass', self.svn_class))

        if dn_info == []:
            msg = 'Repository not enabled for user %s.' % self.user_dn
            raise error.NotFound(msg)

        self.log.debug('Deleting %s from %s ' % (dn_info, dn))
        result = self._delete_object(dn, dn_info)
        self.log.debug('Result: %s' % result)
        return result
Esempio n. 30
0
 def modify(self, list_address, enable):
     """Enable/Disable a mailing list; return True."""
     list_address = self._validate_input(list_address)
     list_info = self.get(list_address)
     if list_info['data'] == []:
         msg = 'Unable to modify mailing list access, no list found.'
         raise error.NotFound(msg)
     dn = list_info['data'][0].__getitem__(0)
     old_result = list_info['data'][0].__getitem__(1)
     old_attrs = {self.list_enable_attr: old_result[self.list_enable_attr]}
     if enable == True:
         new_attrs = {self.list_enable_attr: 'TRUE'}
     elif enable == False:
         new_attrs = {self.list_enable_attr: 'FALSE'}
     else:
         msg = 'enable can only be one of True or False'
         raise error.InputError(msg)
     result = self._modify_attributes(dn, new_attrs, old_attrs)
     self.log.debug('Result: %s' % result)
     return result