Exemplo n.º 1
0
class TopologyGrabber:
    "Grab ui information"
    def __init__(self):
        loginmgr = PersistentLogin("admin","admin")
        self.wsc = NOXWSClient("127.0.0.1", 443, True, loginmgr)

    def response_is_valid(self,response):
        contentType = response.getContentType()
        """
        assert response.status == httplib.OK, \
               "Request error %d (%s) : %s" % \
               (response.status, response.reason, response.getBody())
        assert contentType == "application/json", \
               "Unexpected content type: %s : %s" % \
               (contentType, response.getBody())
        """
        if not response.status == httplib.OK:
            print "Request error %d (%s) : %s\n\t" % \
                   (response.status, response.reason, response.getBody()),
        elif not contentType == "application/json":
            print "Unexpected content type: %s : %s\n\t" % \
                   (contentType, response.getBody()),
        else:    return True
        return False

    def demangle(self, mangled):
        return mangled.split(';')[-1]

    def get_links(self, url="/ws.v1/link"):
        return self.get_info(url)

    def get_hosts(self, url="/ws.v1/host"):
        return self.get_info(url)

    def get_host_info(self, mangled, url="/ws.v1/host/%s"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_locations(self, mangled, url="/ws.v1/host/%s/active/location"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_location_switch(self, mangled, url="/ws.v1/location/%s/config"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_switches(self, url="/ws.v1/switch"):
        return self.get_info(url)

    def get_switch_info(self, mangled, url="/ws.v1/switch/%s"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_info(self, url):
        url = urllib.quote(url)
        # print url # Handy debugger
        response = self.wsc.get(url)
        body = response.getBody()
        if self.response_is_valid(response):
            return eval(body)
        return []
Exemplo n.º 2
0
 def __init__(self):
     loginmgr = PersistentLogin("admin", "admin")
     self.wsc = NOXWSClient("127.0.0.1", 8888, False, loginmgr)
     self.print_progress = True
     self.print_requests = False
Exemplo n.º 3
0
class WSTester:
    def __init__(self):
        loginmgr = PersistentLogin("admin", "admin")
        self.wsc = NOXWSClient("127.0.0.1", 8888, False, loginmgr)
        self.print_progress = True
        self.print_requests = False

    def print_begin(self, text, width=80):
        bar = "="
        side = (width - len(text)) / 2
        print "\n%s %s %s" % (bar * side, text.title(), bar * side)

    def print_start(self, text, blank=False, width=59):
        if blank: fill = " "
        else: fill = "."
        while len(text) > width:
            for i in xrange(width + 1, width / 2, -1):
                if text[i - 1] in (" ", "/"):
                    to_print = text[:i]
                    break
            print to_print
            text = text[len(to_print):]
        if len(text) < width:
            text += " " + fill * (width - len(text) - 1)
        print "%s" % text,

    def print_end(self, text, good=True, width=21):
        if good: cap = " [ OK ]"
        else: cap = " [FAIL]"
        if self.print_requests:
            self.print_start("", blank=True)
        while len(text) > width - len(cap):
            to_print = text[:width]
            if len(text) > width and text[width] != " ":
                to_print = " ".join(to_print.split(" ")[:-1])
            print to_print
            text = text[len(to_print) + 1:]
            self.print_start("", blank=True)
        width = width - len(cap)
        print "%-*s%s" % (width, text, cap)

    def response_is_valid(self, response):
        contentType = response.getContentType()
        assert response.status == httplib.OK, \
               "Request error %d (%s) : %s" % \
               (response.status, response.reason, response.getBody())
        assert contentType == "application/json", \
               "Unexpected content type: %s : %s" % \
               (contentType, response.getBody())
        return True

    def print_get(self, url):
        url = urllib.quote(url)
        response = self.wsc.get(url)
        print "Result: %d %s\n" % (response.status, response.reason)
        body = response.getBody()
        if self.response_is_valid(response):
            print simplejson.dumps(simplejson.loads(body), indent=2)

    def do_auth_event(self, type, dpid, port, mac, ip, username, hostname):
        auth_obj = {
            'type': type,
            'dpid': dpid,
            'port': port,
            'dladdr': mac,
            'nwaddr': ip,
            'username': username,
            'hostname': hostname
        }
        response = self.wsc.putAsJson(auth_obj, "/ws.v1/debug/event/auth")
        self.response_is_valid(response)

    def put_principal(self, principal_type, dirname, principal_name, obj_dict, \
                      notes={}):
        if self.print_progress:
            action = "Putting"
            if principal_type:
                action += " a"
                if 'principal' in notes: action += " (%s)" % notes['principal']
                if "group" in principal_type:
                    action += " %s %s" % tuple(
                        reversed(principal_type.split('/')))
                else:
                    action += " %s" % principal_type
            if dirname:
                action += " into"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % dirname
            if obj_dict:
                action += " with"
                if 'contents' in notes: action += " (%s)" % notes['contents']
                action += " %s" % "/".join(obj_dict.keys())
            self.print_start(action)

        url = urllib.quote("/ws.v1/%s/%s/%s" %
                           (principal_type, dirname, principal_name))
        if self.print_requests:
            print "\nPUT ", url
        response = self.wsc.putAsJson(obj_dict, url)
        self.response_is_valid(response)

        if self.print_progress:
            self.print_end("Placed")

    def delete_principal(self, principal_type, dirname, principal_name, \
                         notes={}):
        if self.print_progress:
            action = "Deleting"
            if principal_type:
                action += " a"
                if 'principal' in notes: action += " (%s)" % notes['principal']
                if "group" in principal_type:
                    action += " %s %s" % tuple(
                        reversed(principal_type.split('/')))
                else:
                    action += " %s" % principal_type
            if principal_name:
                action += " named"
                if 'name' in notes: action += " (%s)" % notes['name']
                action += " %s" % principal_name
            if dirname:
                action += " from"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % dirname
            self.print_start(action)

        url = urllib.quote("/ws.v1/%s/%s/%s" %
                           (principal_type, dirname, principal_name))
        if self.print_requests:
            print "\nDEL ", url
        response = self.wsc.delete(url, {"content-type": "application/json"})
        self.response_is_valid(response)

        if self.print_progress:
            self.print_end("Removed")

    def add_group_member(self, principal_type, group_dir, group_name, \
                         principal_dir, principal_name, principal_class, \
                         notes={}):
        if self.print_progress:
            action = "Adding"
            if principal_type:
                action += " a"
                if 'principal' in notes: action += " (%s)" % notes['principal']
                action += " %s" % principal_type.split("/")[1]
            if principal_name:
                action += " named"
                if 'name' in notes: action += " (%s)" % notes['name']
                action += " %s" % principal_name
            if principal_dir:
                action += " from"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % principal_dir
            if principal_type:
                action += " into a"
                if 'group' in notes: action += " (%s)" % notes['directory']
                action += " %s %s" % tuple(reversed(principal_type.split('/')))
            if group_name:
                action += " named"
                if 'group_name' in notes:
                    action += " (%s)" % notes['group_name']
                action += " %s" % group_name
            if group_dir:
                action += " in"
                if 'group_directory' in notes:
                    action += " (%s)" % notes['group_directory']
                action += " %s" % group_dir

            self.print_start(action)

        url = urllib.quote("/ws.v1/%s/%s/%s/%s/%s/%s" % \
                           (principal_type, group_dir, group_name, \
                            principal_class, principal_dir, principal_name))
        obj_dict = None  # Not used
        if self.print_requests:
            print "\nPUT ", url
        response = self.wsc.putAsJson(obj_dict, url)
        self.response_is_valid(response)

        if self.print_progress:
            self.print_end("Placed")

    def remove_group_member(self, principal_type, group_dir, group_name, \
                            principal_dir, principal_name, principal_class, \
                            notes={}):
        if self.print_progress:
            action = "Removing"
            if principal_type:
                action += " a"
                if 'principal' in notes: action += " (%s)" % notes['principal']
                action += " %s" % principal_class
            if principal_name:
                action += " named"
                if 'name' in notes: action += " (%s)" % notes['name']
                action += " %s" % principal_name
            if principal_dir:
                action += " in"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % principal_dir
            if principal_type:
                action += " from a"
                if 'group' in notes: action += " (%s)" % notes['directory']
                action += " %s %s" % tuple(reversed(principal_type.split('/')))
            if group_name:
                action += " named"
                if 'group_name' in notes:
                    action += " (%s)" % notes['group_name']
                action += " %s" % group_name
            if group_dir:
                action += " in"
                if 'group_directory' in notes:
                    action += " (%s)" % notes['group_directory']
                action += " %s" % group_dir

            self.print_start(action)

        url = urllib.quote("/ws.v1/%s/%s/%s/%s/%s/%s" % \
                            (principal_type, group_dir, group_name, \
                             principal_class, principal_dir, principal_name))
        if self.print_requests:
            print "\nDEL ", url
        response = self.wsc.delete(url, {"content-type": "application/json"})
        self.response_is_valid(response)

        if self.print_progress:
            self.print_end("Removed")

    # does get and makes sure that we get the expected result
    # if 'expected_obj_dict' is None, then we expect a 404
    def verify_get_group_member(self, principal_type, group_dir, group_name, \
                                principal_dir, principal_name, principal_class, \
                                expected_obj_dict, notes={}):
        if self.print_progress:
            action = "Retrieving"
            if principal_type:
                action += " a"
                if 'principal' in notes: action += " (%s)" % notes['principal']
                action += " %s" % principal_type.split("/")[1]
            if principal_name:
                action += " named"
                if 'name' in notes: action += " (%s)" % notes['name']
                action += " %s" % principal_name
            if principal_dir:
                action += " in"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % principal_dir
            if principal_type:
                action += " from a"
                if 'group' in notes: action += " (%s)" % notes['directory']
                action += " %s %s" % tuple(reversed(principal_type.split('/')))
            if group_name:
                action += " named"
                if 'group_name' in notes:
                    action += " (%s)" % notes['group_name']
                action += " %s" % group_name
            if group_dir:
                action += " in"
                if 'group_directory' in notes:
                    action += " (%s)" % notes['group_directory']
                action += " %s" % group_dir
            self.print_start(action)

        url = "/ws.v1/%s/%s/%s/%s/%s/%s" %  \
               (principal_type, group_dir, group_name, \
                principal_class, principal_dir, principal_name)
        url = urllib.quote(url)
        if self.print_requests:
            print "\nGET ", url
        response = self.wsc.get(url)
        if expected_obj_dict == None:
            if response.status == httplib.OK:
                if self.print_progress:
                    self.print_end("Found", good=False)
                print "Expected non-OK value, but got %s: %s" %  \
                (response.status,response.getBody())
            if self.print_progress:
                self.print_end("Expected error")
            return

        if self.print_progress:
            if response.status == httplib.OK:
                self.print_end("Found")
            else:
                self.print_end("Not Found", good=False)

    # does get and makes sure that we get the expected result
    # if 'expected_obj_dict' is None, then we expect a 404
    def verify_get_principal(self, principal_type, dirname, principal_name, \
                             expected_obj_dict, notes={}):
        if self.print_progress:
            action = "Retrieving"
            if principal_type:
                action += " a"
                if expected_obj_dict == None: action += " non-existent"
                if 'principal' in notes: action += " (%s)" % notes['principal']
                if "group" in principal_type:
                    action += " %s %s" % tuple(
                        reversed(principal_type.split('/')))
                else:
                    action += " %s" % principal_type
            if dirname:
                action += " from"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % dirname
            if expected_obj_dict:
                action += " via"
                if 'expected' in notes: action += " (%s)" % notes['expected']
                action += " %s" % "/".join(expected_obj_dict.keys())
            self.print_start(action)

        url = "/ws.v1/%s/%s/%s" % (principal_type, dirname, principal_name)
        url = urllib.quote(url)
        if self.print_requests:
            print "\nGET ", url
        response = self.wsc.get(url)
        if expected_obj_dict == None:
            if response.status == httplib.OK:
                if self.print_progress:
                    self.print_end("Found", good=False)
                print "Expected non-OK value, but got %s: %s" %  \
                (response.status,response.getBody())
            if self.print_progress:
                self.print_end("Expected error")
            return

        if self.response_is_valid(response):
            body = response.getBody()
            actual_obj_dict = simplejson.loads(body)
            assert dict_is_same(actual_obj_dict, expected_obj_dict), \
                   "Mismatched Dictionary\nExpected: '%s'\nGot: '%s'" % \
                   (expected_obj_dict, actual_obj_dict)
        if self.print_progress:
            if expected_obj_dict:
                self.print_end("Found")
            else:
                self.print_end("Expected none")

    # does a search_* and compares the returned list to the expected list
    # if 'dirname' is "" or None, all directories are searched
    def verify_search_principals(self,
                                 principal_type,
                                 dirname,
                                 query,
                                 expected_name_list,
                                 notes={}):
        if self.print_progress:
            action = "Searching"
            if query: action += ""
            else: action += " all"
            if principal_type:
                action += " %s" % principal_type
                action += " lists"
                if 'principal' in notes: action += " (%s)" % notes['principal']
            if dirname:
                action += " in"
                if 'directory' in notes: action += " (%s)" % notes['directory']
                action += " %s" % dirname
            if query:
                action += " by"
                if 'query' in notes: action += " (%s)" % notes['query']
                action += " %s" % "/".join(query.keys())
            self.print_start(action)

        query_str = "?"
        query_args = []
        for key, value in query.iteritems():
            query_args.append(urllib.quote(key) + "=" + urllib.quote(value))
        query_str += "&".join(query_args)

        if dirname is None or dirname == "":
            url = urllib.quote("/ws.v1/%s" % (principal_type))
        else:
            url = urllib.quote("/ws.v1/%s/%s" % (principal_type, dirname))
        if self.print_requests:
            print "\nGET ", url
        response = self.wsc.get(url + query_str)
        if expected_name_list == None:
            if response.status == httplib.OK:
                if self.print_progress:
                    self.print_end("Found", good=False)
                print "Expected NOT_FOUND, but got %s: %s"
                (response.status, response.getBody())
            if self.print_progress:
                self.print_end("Expected error")
            return
        if self.response_is_valid(response):
            body = response.getBody()
            actual_name_list = simplejson.loads(body)
            assert list_is_same(actual_name_list, expected_name_list), \
                   "Mismatched List\n\tExpected: '%s'\n\tGot: '%s'" % \
                    (expected_name_list, actual_name_list)
        if self.print_progress:
            if expected_name_list:
                self.print_end("Found")
            else:
                self.print_end("Expected none")
Exemplo n.º 4
0
 def __init__(self):
     loginmgr = PersistentLogin("admin","admin")
     self.wsc = NOXWSClient("127.0.0.1", 443, True, loginmgr)
     self.debug = True
Exemplo n.º 5
0
class ConsistencyTester:
    "Grab/set ui information"
    def __init__(self):
        loginmgr = PersistentLogin("admin","admin")
        self.wsc = NOXWSClient("127.0.0.1", 443, True, loginmgr)
        self.debug = True

    def response_is_valid(self,response):
        contentType = response.getContentType()
        """
        assert response.status == httplib.OK, \
               "Request error %d (%s) : %s" % \
               (response.status, response.reason, response.getBody())
        assert contentType == "application/json", \
               "Unexpected content type: %s : %s" % \
               (contentType, response.getBody())
        """
        if not response.status == httplib.OK:
            print "Request error %d (%s) : %s\n\t" % \
                   (response.status, response.reason, response.getBody()),
        elif not contentType == "application/json":
            print "Unexpected content type: %s : %s\n\t" % \
                   (contentType, response.getBody()),
        else:    return True
        #self.debug = True
        return False

    def demangle(self, mangled):
        return mangled.split(';')[-1]

    def get_discovered_hosts(self, url="/ws.v1/host/discovered"):
        return self.get_info(url)

    def get_host_info(self, mangled, url="/ws.v1/host/%s"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_active(self, mangled, url="/ws.v1/host/%s/active"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_interfaces(self, mangled,
                           url="/ws.v1/host/%s/active/interface"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_interface(self, mangled, interface,
                           url="/ws.v1/host/%s/interface/%s"):
        return self.get_info(url % (mangled.replace(';','/'), interface))

    def get_info(self, url):
        url = urllib.quote(url)
        if self.debug:  print url
        response = self.wsc.get(url)
        body = response.getBody()
        # hack so that the returned value 'true' is evaluated properly
        true,false = True,False
        if self.response_is_valid(response):
            return eval(body)
        return []

    def put_host_info(self, mangled, info, url="/ws.v1/host/%s"):
        return self.put_info(url % (mangled.replace(';','/')), info)

    def put_dchp_config(self, info, url="/ws.v1/config/dhcp_config"):
        return self.put_info(url, info)

    def put_info(self, url, info):
        url = urllib.quote(url)
        if self.debug:  print url, info
        response = self.wsc.putAsJson(info,url)
        body = response.getBody()
        if self.response_is_valid(response):
            return eval(body)
        return []
Exemplo n.º 6
0
            command = a
        elif o == '-u':
            adminu = a
        elif o == '-p':
            adminp = a
        else:
            assert False, "unhandled option"

    if not directory or not switch or not command:
        usage()
        sys.exit()

    print ' Logging into web service.. ',
    loginmgr = PersistentLogin("admin", "admin")
    # currently only support localhost
    wsc = NOXWSClient("127.0.0.1", 443, True, loginmgr)
    print 'done'

    urlstr = '/ws.v1/switch/' + directory + '/' + switch + '/command'
    print ' Issuing:'
    print '\t', urlstr
    url = urllib.quote(urlstr)

    d = {}
    d['command'] = command
    d['args'] = args
    headers = {}
    headers["content-type"] = "application/json"
    response = wsc.put(url, headers, simplejson.dumps(d))
    body = response.getBody()
Exemplo n.º 7
0
 def __init__(self):
     loginmgr = PersistentLogin("admin","admin")
     self.wsc = NOXWSClient("127.0.0.1", 443, True, loginmgr)
Exemplo n.º 8
0
class HostFiller:
    "Grab/set ui information"
    def __init__(self):
        loginmgr = PersistentLogin("admin","admin")
        self.wsc = NOXWSClient("127.0.0.1", 443, True, loginmgr)
        self.debug = True

    def response_is_valid(self,response):
        contentType = response.getContentType()
        """
        assert response.status == httplib.OK, \
               "Request error %d (%s) : %s" % \
               (response.status, response.reason, response.getBody())
        assert contentType == "application/json", \
               "Unexpected content type: %s : %s" % \
               (contentType, response.getBody())
        """
        if not response.status == httplib.OK:
            print "Request error %d (%s) : %s\n\t" % \
                   (response.status, response.reason, response.getBody()),
        elif not contentType == "application/json":
            print "Unexpected content type: %s : %s\n\t" % \
                   (contentType, response.getBody()),
        else:    return True
        self.debug = True
        return False

    def demangle(self, mangled):
        return mangled.split(';')[-1]

    def get_discovered_hosts(self, url="/ws.v1/host/discovered"):
        return self.get_info(url)

    def get_host_info(self, mangled, url="/ws.v1/host/%s"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_active(self, mangled, url="/ws.v1/host/%s/active"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_interfaces(self, mangled,
                           url="/ws.v1/host/%s/active/interface"):
        return self.get_info(url % (mangled.replace(';','/')))

    def get_host_interface(self, mangled, interface,
                           url="/ws.v1/host/%s/interface/%s"):
        return self.get_info(url % (mangled.replace(';','/'), interface))

    def get_info(self, url):
        url = urllib.quote(url)
        if self.debug:  print url
        response = self.wsc.get(url)
        body = response.getBody()
        # hack so that the returned value 'true' is evaluated properly
        true,false = True,False
        if self.response_is_valid(response):
            return eval(body)
        return []

    def put_host_info(self, mangled, info, url="/ws.v1/host/%s"):
        return self.put_info(url % (mangled.replace(';','/')), info)

    def put_dchp_config(self, info, url="/ws.v1/config/dhcp_config"):
        return self.put_info(url, info)

    def put_info(self, url, info):
        url = urllib.quote(url)
        if self.debug:  print url, info
        response = self.wsc.putAsJson(info,url)
        body = response.getBody()
        if self.response_is_valid(response):
            return eval(body)
        return []
Exemplo n.º 9
0
 def __init__(self): 
   loginmgr = PersistentLogin("admin","admin")
   self.wsc = NOXWSClient("127.0.0.1", 8888, False, loginmgr)
   self.print_progress = True
   self.print_requests = False
Exemplo n.º 10
0
class WSTester: 

  def __init__(self): 
    loginmgr = PersistentLogin("admin","admin")
    self.wsc = NOXWSClient("127.0.0.1", 8888, False, loginmgr)
    self.print_progress = True
    self.print_requests = False

  def print_begin(self, text, width=80):
      bar = "="
      side = (width - len(text))/2
      print "\n%s %s %s" % (bar*side, text.title(), bar*side)

  def print_start(self, text, blank=False, width=59):
      if blank:    fill = " "
      else:        fill = "."
      while len(text) > width:
          for i in xrange(width+1,width/2,-1):
              if text[i-1] in (" ", "/"):
                  to_print = text[:i]
                  break
          print to_print
          text = text[len(to_print):]
      if len(text) < width:
          text += " " + fill*(width-len(text)-1)
      print "%s" % text,

  def print_end(self, text, good=True, width=21):
      if good:    cap = " [ OK ]"
      else:       cap = " [FAIL]"
      if self.print_requests:
          self.print_start("", blank=True)
      while len(text) > width - len(cap):
          to_print = text[:width]
          if len(text) > width and text[width] != " ":
              to_print = " ".join(to_print.split(" ")[:-1])
          print to_print
          text = text[len(to_print)+1:]
          self.print_start("", blank=True)
      width = width - len(cap)
      print "%-*s%s" % (width, text, cap)
   
  def response_is_valid(self,response):
      contentType = response.getContentType()
      assert response.status == httplib.OK, \
             "Request error %d (%s) : %s" % \
             (response.status, response.reason, response.getBody())
      assert contentType == "application/json", \
             "Unexpected content type: %s : %s" % \
             (contentType, response.getBody())
      return True

  def print_get(self, url):
    url = urllib.quote(url)
    response = self.wsc.get(url) 
    print "Result: %d %s\n" % (response.status, response.reason)
    body = response.getBody()
    if self.response_is_valid(response): 
      print simplejson.dumps(simplejson.loads(body), indent=2)

  
  def do_auth_event(self, type,dpid,port,mac,ip,username,hostname): 
      auth_obj = {'type' : type,
                  'dpid' : dpid,
                  'port' : port,
                  'dladdr' : mac,
                  'nwaddr' : ip,
                  'username' : username,
                  'hostname' : hostname
                 } 
      response = self.wsc.putAsJson(auth_obj,"/ws.v1/debug/event/auth") 
      self.response_is_valid(response) 
  
  def put_principal(self, principal_type, dirname, principal_name, obj_dict, \
                    notes={}):
      if self.print_progress:
          action = "Putting"
          if principal_type:
              action += " a"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
              if "group" in principal_type:
                  action += " %s %s"% tuple(reversed(principal_type.split('/')))
              else:
                  action += " %s" % principal_type
          if dirname:
              action += " into"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % dirname
          if obj_dict:
              action += " with"
              if 'contents' in notes:   action += " (%s)" % notes['contents']
              action += " %s" % "/".join(obj_dict.keys())
          self.print_start(action)

      url = urllib.quote("/ws.v1/%s/%s/%s" % (principal_type,dirname,principal_name))
      if self.print_requests:
          print "\nPUT ", url
      response = self.wsc.putAsJson(obj_dict,url) 
      self.response_is_valid(response)

      if self.print_progress:
          self.print_end("Placed")
  
  def delete_principal(self, principal_type, dirname, principal_name, \
                       notes={}):
      if self.print_progress:
          action = "Deleting"
          if principal_type:
              action += " a"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
              if "group" in principal_type:
                  action += " %s %s"% tuple(reversed(principal_type.split('/')))
              else:
                  action += " %s" % principal_type
          if principal_name:
              action += " named"
              if 'name' in notes:       action += " (%s)" % notes['name']
              action += " %s" % principal_name
          if dirname:
              action += " from"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % dirname
          self.print_start(action)

      url = urllib.quote("/ws.v1/%s/%s/%s" % (principal_type,dirname,principal_name))
      if self.print_requests:
          print "\nDEL ", url
      response = self.wsc.delete(url, { "content-type" : "application/json" } )
      self.response_is_valid(response)

      if self.print_progress:
          self.print_end("Removed")
 
  def add_group_member(self, principal_type, group_dir, group_name, \
                       principal_dir, principal_name, principal_class, \
                       notes={}):
      if self.print_progress:
          action = "Adding"
          if principal_type:
              action += " a"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
              action += " %s" % principal_type.split("/")[1]
          if principal_name:
              action += " named"
              if 'name' in notes:  action += " (%s)" % notes['name']
              action += " %s" % principal_name
          if principal_dir:
              action += " from"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % principal_dir
          if principal_type:
              action += " into a"
              if 'group' in notes:  action += " (%s)" % notes['directory']
              action += " %s %s"% tuple(reversed(principal_type.split('/')))
          if group_name:
              action += " named"
              if 'group_name' in notes:  action += " (%s)" % notes['group_name']
              action += " %s" % group_name
          if group_dir:
              action += " in"
              if 'group_directory' in notes:  action += " (%s)" % notes['group_directory']
              action += " %s" % group_dir

          self.print_start(action)

      url = urllib.quote("/ws.v1/%s/%s/%s/%s/%s/%s" % \
                         (principal_type, group_dir, group_name, \
                          principal_class, principal_dir, principal_name))
      obj_dict = None  # Not used
      if self.print_requests:
          print "\nPUT ", url
      response = self.wsc.putAsJson(obj_dict,url) 
      self.response_is_valid(response)

      if self.print_progress:
          self.print_end("Placed")
  
  def remove_group_member(self, principal_type, group_dir, group_name, \
                          principal_dir, principal_name, principal_class, \
                          notes={}):
      if self.print_progress:
          action = "Removing"
          if principal_type:
              action += " a"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
              action += " %s" % principal_class
          if principal_name:
              action += " named"
              if 'name' in notes:  action += " (%s)" % notes['name']
              action += " %s" % principal_name
          if principal_dir:
              action += " in"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % principal_dir
          if principal_type:
              action += " from a"
              if 'group' in notes:  action += " (%s)" % notes['directory']
              action += " %s %s"% tuple(reversed(principal_type.split('/')))
          if group_name:
              action += " named"
              if 'group_name' in notes:  action += " (%s)" % notes['group_name']
              action += " %s" % group_name
          if group_dir:
              action += " in"
              if 'group_directory' in notes:  action += " (%s)" % notes['group_directory']
              action += " %s" % group_dir

          self.print_start(action)

      url = urllib.quote("/ws.v1/%s/%s/%s/%s/%s/%s" % \
                          (principal_type, group_dir, group_name, \
                           principal_class, principal_dir, principal_name))
      if self.print_requests:
          print "\nDEL ", url
      response = self.wsc.delete(url, { "content-type" : "application/json" } )
      self.response_is_valid(response)

      if self.print_progress:
          self.print_end("Removed")

  # does get and makes sure that we get the expected result
  # if 'expected_obj_dict' is None, then we expect a 404
  def verify_get_group_member(self, principal_type, group_dir, group_name, \
                              principal_dir, principal_name, principal_class, \
                              expected_obj_dict, notes={}):
      if self.print_progress:
          action = "Retrieving"
          if principal_type:
              action += " a"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
              action += " %s" % principal_type.split("/")[1]
          if principal_name:
              action += " named"
              if 'name' in notes:  action += " (%s)" % notes['name']
              action += " %s" % principal_name
          if principal_dir:
              action += " in"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % principal_dir
          if principal_type:
              action += " from a"
              if 'group' in notes:  action += " (%s)" % notes['directory']
              action += " %s %s"% tuple(reversed(principal_type.split('/')))
          if group_name:
              action += " named"
              if 'group_name' in notes:  action += " (%s)" % notes['group_name']
              action += " %s" % group_name
          if group_dir:
              action += " in"
              if 'group_directory' in notes:  action += " (%s)" % notes['group_directory']
              action += " %s" % group_dir
          self.print_start(action)

      url = "/ws.v1/%s/%s/%s/%s/%s/%s" %  \
             (principal_type, group_dir, group_name, \
              principal_class, principal_dir, principal_name)
      url = urllib.quote(url)
      if self.print_requests:
          print "\nGET ", url
      response = self.wsc.get(url) 
      if expected_obj_dict == None: 
        if response.status == httplib.OK:
          if self.print_progress:
              self.print_end("Found", good=False)
          print "Expected non-OK value, but got %s: %s" %  \
          (response.status,response.getBody())
        if self.print_progress:
            self.print_end("Expected error")
        return

      if self.print_progress:
          if response.status == httplib.OK:
              self.print_end("Found")
          else:
              self.print_end("Not Found", good=False)
 
  # does get and makes sure that we get the expected result
  # if 'expected_obj_dict' is None, then we expect a 404
  def verify_get_principal(self, principal_type, dirname, principal_name, \
                           expected_obj_dict, notes={}):
      if self.print_progress:
          action = "Retrieving"
          if principal_type:
              action += " a"
              if expected_obj_dict == None:  action += " non-existent"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
              if "group" in principal_type:
                  action += " %s %s"% tuple(reversed(principal_type.split('/')))
              else:
                  action += " %s" % principal_type
          if dirname:
              action += " from"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % dirname
          if expected_obj_dict:
              action += " via"
              if 'expected' in notes:      action += " (%s)" % notes['expected']
              action += " %s" % "/".join(expected_obj_dict.keys())
          self.print_start(action)

      url = "/ws.v1/%s/%s/%s" % (principal_type,dirname,principal_name)
      url = urllib.quote(url)
      if self.print_requests:
          print "\nGET ", url
      response = self.wsc.get(url) 
      if expected_obj_dict == None: 
        if response.status == httplib.OK:
          if self.print_progress:
              self.print_end("Found", good=False)
          print "Expected non-OK value, but got %s: %s" %  \
          (response.status,response.getBody())
        if self.print_progress:
            self.print_end("Expected error")
        return

      if self.response_is_valid(response):
        body = response.getBody()
        actual_obj_dict = simplejson.loads(body)
        assert dict_is_same(actual_obj_dict, expected_obj_dict), \
               "Mismatched Dictionary\nExpected: '%s'\nGot: '%s'" % \
               (expected_obj_dict, actual_obj_dict)
      if self.print_progress:
          if expected_obj_dict:
              self.print_end("Found")
          else:
              self.print_end("Expected none")
 
  # does a search_* and compares the returned list to the expected list
  # if 'dirname' is "" or None, all directories are searched
  def verify_search_principals(self, principal_type, dirname, 
                               query, expected_name_list, notes={}):
      if self.print_progress:
          action = "Searching"
          if query:  action += ""
          else:      action += " all"
          if principal_type:
              action += " %s" % principal_type
              action += " lists"
              if 'principal' in notes:  action += " (%s)" % notes['principal']
          if dirname:
              action += " in"
              if 'directory' in notes:  action += " (%s)" % notes['directory']
              action += " %s" % dirname
          if query:
              action += " by"
              if 'query' in notes:      action += " (%s)" % notes['query']
              action += " %s" % "/".join(query.keys())
          self.print_start(action)

      query_str = "?"
      query_args = []
      for key,value in query.iteritems():
        query_args.append(urllib.quote(key) + "=" + urllib.quote(value))
      query_str += "&".join(query_args)

      if dirname is None or dirname == "": 
        url = urllib.quote("/ws.v1/%s" % (principal_type))
      else :  
        url = urllib.quote("/ws.v1/%s/%s" % (principal_type,dirname))
      if self.print_requests:
          print "\nGET ", url
      response = self.wsc.get(url + query_str) 
      if expected_name_list == None: 
        if response.status == httplib.OK:
          if self.print_progress:
              self.print_end("Found", good=False)
          print "Expected NOT_FOUND, but got %s: %s" 
          (response.status,response.getBody())
        if self.print_progress:
            self.print_end("Expected error")
        return
      if self.response_is_valid(response):
        body = response.getBody()
        actual_name_list = simplejson.loads(body)
        assert list_is_same(actual_name_list, expected_name_list), \
               "Mismatched List\n\tExpected: '%s'\n\tGot: '%s'" % \
                (expected_name_list, actual_name_list)
      if self.print_progress:
          if expected_name_list:
              self.print_end("Found")
          else:
              self.print_end("Expected none")