Beispiel #1
0
    def do_DELETE(self):
        Log.info('DELETE {}:{}', self.server.node_address, self.path)

        path = self.normalize_path(self.path)
        parent_path = path.rsplit(os.sep, 1)[0]

        #
        # If the resource doesn't exist, then 404.
        # If the parent doesn't exist, then 405.
        # If the parent isn't a collection, then 405.
        # Otherwise, 204
        #
        if path not in self.server.cache:
            status = 404
        elif parent_path not in self.server.cache:
            status = 405
        elif 'Members' not in self.server.cache[parent_path]:
            status = 405
        else:
            status = 204

            del self.server.cache[path]
            for i,m in enumerate(self.server.cache[parent_path]['Members']):
                if m['@odata.id'] == self.path:
                    del self.server.cache[parent_path]['Members'][i]
                    self.server.cache[parent_path]['*****@*****.**'] -= 1
                    break

        self.reply(status)
Beispiel #2
0
    def do_PUT(self):
        Log.info('PUT {}:{}', self.server.node_address, self.path)

        #
        # We don't support this function.
        #
        self.reply(405)
Beispiel #3
0
    def do_PATCH(self):
        Log.info('PATCH {}:{}', self.server.node_address, self.path)

        path = self.normalize_path(self.path)

        data_length = int(self.headers["content-length"])
        data = json.loads(self.rfile.read(data_length).decode("utf-8"))
        data_id = data['@odata.id']

        #
        # If the resource doesn't exist, then 404.
        # If the resource is a collection, then 405.
        # Otherwise, 204.
        #
        if path not in self.server.cache:
            self.reply(404)
        elif 'Members' in self.server.cache[path]:
            self.reply(405)
        else:
            #
            # Update the resource.
            #
            update_resource(self.server.cache[path], data)

            #
            # Reply to the user.
            #
            headers = { "Location" : data_id, "Content-Length" : "0" }
            self.reply(204, headers)
Beispiel #4
0
    def do_POST(self):
        Log.info('POST {}:{}', self.server.node_address, self.path)

        path = self.normalize_path(self.path)

        data_length = int(self.headers["content-length"])
        data = json.loads(self.rfile.read(data_length).decode("utf-8"))
        data_id = data['@odata.id']

        #
        # If the resource doesn't exist, then 404.
        # If the resource isn't a collection, then 405.
        # Otherwise, 204
        #
        if path not in self.server.cache:
            self.reply(404)
        elif 'Members' not in self.server.cache[path]:
            self.reply(405)
        else:
            #
            # Find a resource id for the new entry.
            #
            resource = self.server.cache[path]
            members = resource['Members']
            members_id = sorted([ int(x.get('@odata.id').rsplit(os.sep,1)[1]) for x in members ])

            last = members_id[0]
            for x in members_id[1:]:
                if x != last+1: break
                last = x

            #
            # Name the new entry.
            #
            new_id = last + 1
            data_id = data_id.rsplit(os.sep, 1)[0]
            data_id = os.path.join(data_id, str(new_id))
            data['@odata.id'] = data_id

            #
            # Update the resource to include the new entry.
            #
            resource['Members'].append({'@odata.id' : data_id })
            resource['*****@*****.**'] += 1

            #
            # Put the new entry into the tree.  (The resource name doesn't have a leading '/'.)
            #
            new_id = data_id
            if new_id[0] == os.sep: new_id = new_id[1:]
            self.server.cache[new_id] = data

            #
            # Reply to the user.
            #
            headers = { "Location" : data_id, "Content-Length" : "0" }
            self.reply(204, headers)
Beispiel #5
0
    def initialize(self):

        #
        # Validate the sweep type.
        #
        if self.sweep_type not in Fabric.sweep_types:
            Log.error('invalid sweep type {}', self.sweep_type)
            return False

        #
        # Read the node profiles.
        #
        self.nodes = {}
        for filename in self.node_file_list:
            Log.info('reading {}', filename)
            try:
                with open(filename) as f:
                    node_profiles = json.load(f)
                    for name, profile in node_profiles.items():
                        node_type = profile['type']
                        self.nodes[name] = Fabric.name_classes[node_type](
                            name, profile)
            except:
                Log.error('error reading {}', filename)
                return False

        #
        # There are 5 steps for node initialization:
        #   1) load the GCIDs and UID into the endpoints
        #   2) train the port links
        #   3) validate that all ports are wired correctly
        #   4) load the node attributes
        #   5) enable the port interfaces
        #
        status = True

        if status: status = self.init_ids()
        if status: status = self.train_ports()
        if status: status = self.validate_ports()
        if status: status = self.load_nodes()
        if status: status = self.enable_ports()

        #
        # Verify the state of all connected ports.
        #
        if status:
            status = self.verify_fabric_health()

        Log.debug('fabric initialization status = {}', status)
        return status
Beispiel #6
0
    def wait_for(self, command, args, kwargs):
        Log.info('starting {}...', command)
        kwargs['retries'] = self.timers.get(command, self.timers['default'])
        verify_name = '{}_done'.format(command)

        #
        # Tell the node threads to start the command.
        #
        active_nodes = [node for node in self.nodes.values() if node.active]
        for node in active_nodes:
            node.enqueue(command, args, kwargs)

        #
        # Wait for all of the node threads to complete.
        #
        cycles = 0
        node_statuses = [-1]
        while (self.wait_status(node_statuses) < 0) and (cycles <
                                                         self.timers[command]):
            time.sleep(1)
            cycles += 1

            node_statuses = [
                getattr(node, verify_name)() for node in active_nodes
            ]
            if (cycles % 60) == 0:
                self.wait_display(command, cycles, node_statuses)

        #
        # Check for node timeouts.
        #
        if self.wait_status(node_statuses) < 0:
            self.wait_display(command, cycles, node_statuses)

            for i in range(len(node_statuses)):
                if node_statuses[i] == -1:
                    Log.error('{} : {} timed out', command,
                              active_nodes[i].name)

        #
        # Display the command status.
        #
        command_status = self.wait_status(node_statuses) == 1
        Log.info('{} done ... status = {}   cycles = {}', command,
                 command_status, cycles)
        return command_status
Beispiel #7
0
    #
    # Create the fabric and server.
    #
    fabric = Fabric(zfm_sweep_type, timers, config_files)
    server = Server(hostname, fabric)

    #
    # Initialize the fabric.
    #
    try:
        if not fabric.initialize():
            Log.error('fabric initialization failed')
            sys.exit(1)
    except KeyboardInterrupt:
        Log.info('user interrupt caught - exiting')
        sys.exit(1)

    #
    # Start the HTTP server.
    #
    server_thread = Thread(target=server.run, daemon=True)
    server_thread.start()

    #
    # Monitor the fabric.
    #
    try:
        while True:
            fabric.sweep()
            time.sleep(timers['sweep'])
Beispiel #8
0
 def run(self):
     Log.info('starting ZFM server @ {}:{}', self.address, self.port)
     self.server.serve_forever()
Beispiel #9
0
    def do_GET(self):
        if 'favicon.ico' in self.path:
            return 404, None

        Log.info('GET {}:{}', self.server.node_address, self.path)

        parsed_url = parse.urlsplit(self.path)
        tokens = parsed_url.path.split('/')
        query = parsed_url.query
        parameters = parse.parse_qs(query)

        if 'format' not in parameters: parameters['format'] = ['BROWSER']

        #
        # Remove empty strings from the parsed URL.
        #
        while (len(tokens) > 0) and (tokens[0] == ''):
            del tokens[0]

        while (len(tokens) > 0) and (tokens[-1] == ''):
            del tokens[-1]

        if (len(tokens) > 0) and (tokens[-1] == 'favicon.ico'):
            return 404, None

        #
        # Valid requests are:
        #   1) []          -> fabric request
        #   2) [name]      -> node request
        #   3) [name,port] -> port request
        #
        status,data = 404,None

        fabric = self.server.fabric
        node = None
        port = None

        #
        # Validate that the parameters are in range and correct.
        #
        if len(tokens) > 2:
            Log.error('too many fields in URL {}', self.path)
            return 404, None

        if len(tokens) == 2 and not tokens[1].isdigit():
            Log.error('invalid URL (port incorrect) {}', self.path)
            return 404, None

        if len(tokens) >= 1:
            node = self.server.fabric.locate_node(tokens[0])
            if not node:
                Log.error('invalid URL (node incorrect) {}', self.path)
                return 404, None

        if len(tokens) == 2:
            value = int(tokens[1])
            if not (node.profile['portStart'] <= value < node.profile['portEnd']):
                Log.error('invalid URL (port out of range) {}', self.path)
                return 404, None
            port = node.ports[value]

        #
        # Execute the command at the appropriate level.
        #
        if len(tokens) == 0:
            status, data = fabric.GET(parameters)
        elif len(tokens) == 1:
            status, data = node.GET(parameters)
        elif len(tokens) == 2:
            status, data = port.GET(parameters)

        if status == 200:
            data['ZFM'] = self.server.node_address
            output = self.server.formatter.format(data, parameters['format'][0])

        #
        # Send the reply back to the requester.
        #
        headers = {'Content-type'  :  'text/html',
                   'Cache-Control' :  'no-cache, no-store, must-revalidate',
                   'Pragma'        :  'no-cache',
                   'Expires'       :  '0' }

        payload = output if status == 200 else None

        self.reply(status, headers, payload)
Beispiel #10
0
 def wait_display(self, command, cycles, statuses):
     s = {-1: '-', 0: '0', 1: '1'}
     status_str = ''.join(s[x] for x in statuses)
     Log.info('{} : cycles={:<4}  status={:<}', command, cycles, status_str)