Example #1
0
func HandleRequest(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
	start := time.Now()

	// Get API request type.
	requestType := u.Path[len(ApiResource):]
	i := strings.Index(requestType, "/")
	requestArgs := ""
	if i != -1 {
		requestArgs = requestType[i:]
		requestType = requestType[:i]
	}

	if requestType == MachineApi {
		log.Printf("Api - Machine")

		// Get the MachineInfo
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}

		out, err := json.Marshal(machineInfo)
		if err != nil {
			fmt.Fprintf(w, "Failed to marshall MachineInfo with error: %s", err)
		}
		w.Write(out)
	} else if requestType == ContainersApi {
		// The container name is the path after the requestType
		containerName := requestArgs

		log.Printf("Api - Container(%s)", containerName)

		// Get the container.
		cont, err := m.GetContainerInfo(containerName)
		if err != nil {
			fmt.Fprintf(w, "Failed to get container \"%s\" with error: %s", containerName, err)
			return err
		}

		// Only output the container as JSON.
		out, err := json.Marshal(cont)
		if err != nil {
			fmt.Fprintf(w, "Failed to marshall container %q with error: %s", containerName, err)
		}
		w.Write(out)
	} else {
		return fmt.Errorf("unknown API request type %q", requestType)
	}

	log.Printf("Request took %s", time.Since(start))
	return nil
}
Example #2
0
func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
	start := time.Now()

	// The container name is the path after the handler
	containerName := u.Path[len(ContainersPage)-1:]

	// Get the container.
	cont, err := m.GetContainerInfo(containerName)
	if err != nil {
		return fmt.Errorf("Failed to get container \"%s\" with error: %s", containerName, err)
	}

	// Get the MachineInfo
	machineInfo, err := m.GetMachineInfo()
	if err != nil {
		return err
	}

	// Make a list of the parent containers and their links
	var parentContainers []string
	parentContainers = append(parentContainers, string("root"))
	parentName := ""
	for _, part := range strings.Split(string(cont.Name), "/") {
		if part == "" {
			continue
		}
		parentName += "/" + part
		parentContainers = append(parentContainers, string(parentName))
	}

	data := &pageData{
		ContainerName:      cont.Name,
		ParentContainers:   parentContainers,
		Subcontainers:      cont.Subcontainers,
		Spec:               cont.Spec,
		Stats:              cont.Stats,
		MachineInfo:        machineInfo,
		ResourcesAvailable: cont.Spec.Cpu != nil || cont.Spec.Memory != nil,
		CpuAvailable:       cont.Spec.Cpu != nil,
		MemoryAvailable:    cont.Spec.Memory != nil,
	}
	err = pageTemplate.Execute(w, data)
	if err != nil {
		log.Printf("Failed to apply template: %s", err)
	}

	log.Printf("Request took %s", time.Since(start))
	return nil
}
Example #3
0
func (self *version1_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
	switch requestType {
	case machineApi:
		glog.V(4).Infof("Api - Machine")

		// Get the MachineInfo
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}

		err = writeResult(machineInfo, w)
		if err != nil {
			return err
		}
	case containersApi:
		containerName := getContainerName(request)
		glog.V(4).Infof("Api - Container(%s)", containerName)

		// Get the query request.
		query, err := getContainerInfoRequest(r.Body)
		if err != nil {
			return err
		}

		// Get the container.
		cont, err := m.GetContainerInfo(containerName, query)
		if err != nil {
			return fmt.Errorf("failed to get container %q with error: %s", containerName, err)
		}

		// Only output the container as JSON.
		err = writeResult(cont, w)
		if err != nil {
			return err
		}
	default:
		return fmt.Errorf("unknown request type %q", requestType)
	}
	return nil
}
Example #4
0
func validateIoScheduler(containerManager manager.Manager) (string, string) {
	var desc string
	mi, err := containerManager.GetMachineInfo()
	if err != nil {
		return Unknown, "Machine info not available\n\t"
	}
	cfq := false
	for _, disk := range mi.DiskMap {
		desc += fmt.Sprintf("\t Disk %q Scheduler type %q.\n", disk.Name, disk.Scheduler)
		if disk.Scheduler == "cfq" {
			cfq = true
		}
	}
	// Since we get lot of random block devices, report recommended if
	// at least one of them is on cfq. Report Supported otherwise.
	if cfq {
		desc = "At least one device supports 'cfq' I/O scheduler. Some disk stats can be reported.\n" + desc
		return Recommended, desc
	}
	desc = "None of the devices support 'cfq' I/O scheduler. No disk stats can be reported.\n" + desc
	return Supported, desc
}
Example #5
0
func (self *version2_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
	opt, err := getRequestOptions(r)
	if err != nil {
		return err
	}
	switch requestType {
	case versionApi:
		glog.V(4).Infof("Api - Version")
		versionInfo, err := m.GetVersionInfo()
		if err != nil {
			return err
		}
		return writeResult(versionInfo.CadvisorVersion, w)
	case attributesApi:
		glog.V(4).Info("Api - Attributes")

		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}
		versionInfo, err := m.GetVersionInfo()
		if err != nil {
			return err
		}
		info := v2.GetAttributes(machineInfo, versionInfo)
		return writeResult(info, w)
	case machineApi:
		glog.V(4).Info("Api - Machine")

		// TODO(rjnagal): Move machineInfo from v1.
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}
		return writeResult(machineInfo, w)
	case summaryApi:
		containerName := getContainerName(request)
		glog.V(4).Infof("Api - Summary for container %q, options %+v", containerName, opt)

		stats, err := m.GetDerivedStats(containerName, opt)
		if err != nil {
			return err
		}
		return writeResult(stats, w)
	case statsApi:
		name := getContainerName(request)
		glog.V(4).Infof("Api - Stats: Looking for stats for container %q, options %+v", name, opt)
		conts, err := m.GetRequestedContainersInfo(name, opt)
		if err != nil {
			return err
		}
		contStats := make(map[string][]v2.ContainerStats, 0)
		for name, cont := range conts {
			contStats[name] = convertStats(cont)
		}
		return writeResult(contStats, w)
	case customMetricsApi:
		containerName := getContainerName(request)
		glog.V(4).Infof("Api - Custom Metrics: Looking for metrics for container %q, options %+v", containerName, opt)
		conts, err := m.GetRequestedContainersInfo(containerName, opt)
		if err != nil {
			return err
		}
		contMetrics := make(map[string]map[string]map[string][]info.MetricValBasic, 0)
		for _, cont := range conts {
			metrics := make(map[string]map[string][]info.MetricValBasic, 0)
			contStats := convertStats(cont)
			for _, contStat := range contStats {
				if contStat.HasCustomMetrics {
					for name, allLabels := range contStat.CustomMetrics {
						metricLabels := make(map[string][]info.MetricValBasic, 0)
						for _, metric := range allLabels {
							if !metric.Timestamp.IsZero() {
								metVal := info.MetricValBasic{
									Timestamp:  metric.Timestamp,
									IntValue:   metric.IntValue,
									FloatValue: metric.FloatValue,
								}
								labels := metrics[name]
								if labels != nil {
									values := labels[metric.Label]
									values = append(values, metVal)
									labels[metric.Label] = values
									metrics[name] = labels
								} else {
									metricLabels[metric.Label] = []info.MetricValBasic{metVal}
									metrics[name] = metricLabels
								}
							}
						}
					}
				}
			}
			contMetrics[containerName] = metrics
		}
		return writeResult(contMetrics, w)
	case specApi:
		containerName := getContainerName(request)
		glog.V(4).Infof("Api - Spec for container %q, options %+v", containerName, opt)
		specs, err := m.GetContainerSpec(containerName, opt)
		if err != nil {
			return err
		}
		return writeResult(specs, w)
	case storageApi:
		var err error
		fi := []v2.FsInfo{}
		label := r.URL.Query().Get("label")
		if len(label) == 0 {
			// Get all global filesystems info.
			fi, err = m.GetFsInfo("")
			if err != nil {
				return err
			}
		} else {
			// Get a specific label.
			fi, err = m.GetFsInfo(label)
			if err != nil {
				return err
			}
		}
		return writeResult(fi, w)
	case eventsApi:
		return handleEventRequest(request, m, w, r)
	case psApi:
		// reuse container type from request.
		// ignore recursive.
		// TODO(rjnagal): consider count to limit ps output.
		name := getContainerName(request)
		glog.V(4).Infof("Api - Spec for container %q, options %+v", name, opt)
		ps, err := m.GetProcessList(name, opt)
		if err != nil {
			return fmt.Errorf("process listing failed: %v", err)
		}
		return writeResult(ps, w)
	default:
		return fmt.Errorf("unknown request type %q", requestType)
	}
}
Example #6
0
func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
	start := time.Now()

	// The container name is the path after the handler
	containerName := u.Path[len(DockerPage):]
	rootDir := getRootDir(u.Path)

	var data *pageData
	if containerName == "" {
		// Get the containers.
		reqParams := info.ContainerInfoRequest{
			NumStats: 0,
		}
		conts, err := m.AllDockerContainers(&reqParams)
		if err != nil {
			return fmt.Errorf("failed to get container %q with error: %v", containerName, err)
		}
		subcontainers := make([]link, 0, len(conts))
		for _, cont := range conts {
			subcontainers = append(subcontainers, link{
				Text: getContainerDisplayName(cont.ContainerReference),
				Link: path.Join("/docker", docker.ContainerNameToDockerId(cont.ContainerReference.Name)),
			})
		}

		// Get Docker status
		status, err := m.DockerInfo()
		if err != nil {
			return err
		}

		dockerStatus, driverStatus := toStatusKV(status)
		// Get Docker Images
		images, err := m.DockerImages()
		if err != nil {
			return err
		}

		dockerContainersText := "Docker Containers"
		data = &pageData{
			DisplayName: dockerContainersText,
			ParentContainers: []link{
				{
					Text: dockerContainersText,
					Link: DockerPage,
				}},
			Subcontainers:      subcontainers,
			Root:               rootDir,
			DockerStatus:       dockerStatus,
			DockerDriverStatus: driverStatus,
			DockerImages:       images,
		}
	} else {
		// Get the container.
		reqParams := info.ContainerInfoRequest{
			NumStats: 60,
		}
		cont, err := m.DockerContainer(containerName, &reqParams)
		if err != nil {
			return fmt.Errorf("failed to get container %q with error: %v", containerName, err)
		}
		displayName := getContainerDisplayName(cont.ContainerReference)

		// Make a list of the parent containers and their links
		var parentContainers []link
		parentContainers = append(parentContainers, link{
			Text: "Docker containers",
			Link: DockerPage,
		})
		parentContainers = append(parentContainers, link{
			Text: displayName,
			Link: path.Join(DockerPage, docker.ContainerNameToDockerId(cont.Name)),
		})

		// Get the MachineInfo
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}
		data = &pageData{
			DisplayName:        displayName,
			ContainerName:      cont.Name,
			ParentContainers:   parentContainers,
			Spec:               cont.Spec,
			Stats:              cont.Stats,
			MachineInfo:        machineInfo,
			ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
			CpuAvailable:       cont.Spec.HasCpu,
			MemoryAvailable:    cont.Spec.HasMemory,
			NetworkAvailable:   cont.Spec.HasNetwork,
			FsAvailable:        cont.Spec.HasFilesystem,
			Root:               rootDir,
		}
	}

	err := pageTemplate.Execute(w, data)
	if err != nil {
		glog.Errorf("Failed to apply template: %s", err)
	}

	glog.V(5).Infof("Request took %s", time.Since(start))
	return nil
}
func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
	start := time.Now()

	// The container name is the path after the handler
	containerName := u.Path[len(ContainersPage)-1:]

	// Get the container.
	reqParams := info.ContainerInfoRequest{
		NumStats:   60,
		NumSamples: 60,
	}
	cont, err := m.GetContainerInfo(containerName, &reqParams)
	if err != nil {
		return fmt.Errorf("Failed to get container \"%s\" with error: %s", containerName, err)
	}

	// Get the MachineInfo
	machineInfo, err := m.GetMachineInfo()
	if err != nil {
		return err
	}

	// Make a list of the parent containers and their links
	var parentContainers []info.ContainerReference
	parentContainers = append(parentContainers, info.ContainerReference{Name: "root"})
	parentName := ""
	for _, part := range strings.Split(string(cont.Name), "/") {
		if part == "" {
			continue
		}
		parentName += "/" + part
		parentContainers = append(parentContainers, info.ContainerReference{Name: parentName})
	}

	// Pick the shortest name of the container as the display name.
	displayName := cont.Name
	for _, alias := range cont.Aliases {
		if len(displayName) >= len(alias) {
			displayName = alias
		}
	}

	// Replace the last part of the parent containers with the displayName.
	if displayName != cont.Name {
		parentContainers[len(parentContainers)-1] = info.ContainerReference{
			Name: fmt.Sprintf("%s (%s)", displayName, path.Base(cont.Name)),
		}
	}

	data := &pageData{
		ContainerName: displayName,
		// TODO(vmarmol): Only use strings for this.
		ParentContainers:   parentContainers,
		Subcontainers:      cont.Subcontainers,
		Spec:               cont.Spec,
		Stats:              cont.Stats,
		MachineInfo:        machineInfo,
		ResourcesAvailable: cont.Spec.Cpu != nil || cont.Spec.Memory != nil,
		CpuAvailable:       cont.Spec.Cpu != nil,
		MemoryAvailable:    cont.Spec.Memory != nil,
	}
	err = pageTemplate.Execute(w, data)
	if err != nil {
		log.Printf("Failed to apply template: %s", err)
	}

	log.Printf("Request took %s", time.Since(start))
	return nil
}
Example #8
0
func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
	start := time.Now()

	// The container name is the path after the handler
	containerName := u.Path[len(ContainersPage)-1:]

	// Get the container.
	reqParams := info.ContainerInfoRequest{
		NumStats: 60,
	}
	cont, err := m.GetContainerInfo(containerName, &reqParams)
	if err != nil {
		return fmt.Errorf("failed to get container %q with error: %v", containerName, err)
	}
	displayName := getContainerDisplayName(cont.ContainerReference)

	// Get the MachineInfo
	machineInfo, err := m.GetMachineInfo()
	if err != nil {
		return err
	}

	// Make a list of the parent containers and their links
	pathParts := strings.Split(string(cont.Name), "/")
	parentContainers := make([]link, 0, len(pathParts))
	parentContainers = append(parentContainers, link{
		Text: "root",
		Link: ContainersPage,
	})
	for i := 1; i < len(pathParts); i++ {
		// Skip empty parts.
		if pathParts[i] == "" {
			continue
		}
		parentContainers = append(parentContainers, link{
			Text: pathParts[i],
			Link: path.Join(ContainersPage, path.Join(pathParts[1:i+1]...)),
		})
	}

	// Build the links for the subcontainers.
	subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
	for _, sub := range cont.Subcontainers {
		subcontainerLinks = append(subcontainerLinks, link{
			Text: getContainerDisplayName(sub),
			Link: path.Join(ContainersPage, sub.Name),
		})
	}

	data := &pageData{
		DisplayName:        displayName,
		ContainerName:      cont.Name,
		ParentContainers:   parentContainers,
		Subcontainers:      subcontainerLinks,
		Spec:               cont.Spec,
		Stats:              cont.Stats,
		MachineInfo:        machineInfo,
		IsRoot:             cont.Name == "/",
		ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork || cont.Spec.HasFilesystem,
		CpuAvailable:       cont.Spec.HasCpu,
		MemoryAvailable:    cont.Spec.HasMemory,
		NetworkAvailable:   cont.Spec.HasNetwork,
		FsAvailable:        cont.Spec.HasFilesystem,
	}
	err = pageTemplate.Execute(w, data)
	if err != nil {
		glog.Errorf("Failed to apply template: %s", err)
	}

	glog.V(1).Infof("Request took %s", time.Since(start))
	return nil
}
Example #9
0
func handleRequest(m manager.Manager, w http.ResponseWriter, r *http.Request) error {
	start := time.Now()

	request := r.URL.Path
	requestElements := strings.Split(r.URL.Path, "/")

	// Verify that we have all the elements we expect:
	// <empty>/api/<version>/<request type>[/<args...>]
	// [0]     [1] [2]       [3]             [4...]
	if len(requestElements) < 4 {
		return fmt.Errorf("incomplete API request %q", request)
	}

	// Get all the element parts.
	emptyElement := requestElements[0]
	apiElement := requestElements[1]
	version := requestElements[2]
	requestType := requestElements[3]
	requestArgs := []string{}
	if len(requestElements) > 4 {
		requestArgs = requestElements[4:]
	}

	// The container name is the path after the requestType.
	containerName := path.Join("/", strings.Join(requestArgs, "/"))

	// Check elements.
	if len(emptyElement) != 0 {
		return fmt.Errorf("unexpected API request format %q", request)
	}
	if apiElement != "api" {
		return fmt.Errorf("invalid API request format %q", request)
	}
	if _, ok := supportedApiVersions[version]; !ok {
		return fmt.Errorf("unsupported API version %q", version)
	}

	switch {
	case requestType == machineApi:
		glog.V(2).Infof("Api - Machine")

		// Get the MachineInfo
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}

		err = writeResult(machineInfo, w)
		if err != nil {
			return err
		}
	case requestType == containersApi:
		glog.V(2).Infof("Api - Container(%s)", containerName)

		// Get the query request.
		query, err := getContainerInfoRequest(r.Body)
		if err != nil {
			return err
		}

		// Get the container.
		cont, err := m.GetContainerInfo(containerName, query)
		if err != nil {
			return fmt.Errorf("failed to get container %q with error: %s", containerName, err)
		}

		// Only output the container as JSON.
		err = writeResult(cont, w)
		if err != nil {
			return err
		}
	case requestType == subcontainersApi:
		if version == version1_0 {
			return fmt.Errorf("request type of %q not supported in API version %q", requestType, version)
		}

		glog.V(2).Infof("Api - Subcontainers(%s)", containerName)

		// Get the query request.
		query, err := getContainerInfoRequest(r.Body)
		if err != nil {
			return err
		}

		// Get the subcontainers.
		containers, err := m.SubcontainersInfo(containerName, query)
		if err != nil {
			return fmt.Errorf("failed to get subcontainers for container %q with error: %s", containerName, err)
		}

		// Only output the containers as JSON.
		err = writeResult(containers, w)
		if err != nil {
			return err
		}
	case requestType == dockerApi:
		if version == version1_0 || version == version1_1 {
			return fmt.Errorf("request type of %q not supported in API version %q", requestType, version)
		}

		glog.V(2).Infof("Api - Docker(%s)", containerName)

		// Get the query request.
		query, err := getContainerInfoRequest(r.Body)
		if err != nil {
			return err
		}

		// Get the Docker containers.
		containers, err := m.DockerContainersInfo(containerName, query)
		if err != nil {
			return fmt.Errorf("failed to get docker containers for %q with error: %s", containerName, err)
		}

		// Only output the containers as JSON.
		err = writeResult(containers, w)
		if err != nil {
			return err
		}
	default:
		return fmt.Errorf("unknown API request type %q", requestType)
	}

	glog.V(2).Infof("Request took %s", time.Since(start))
	return nil
}
func (self *version2_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
	opt, err := getRequestOptions(r)
	if err != nil {
		return err
	}
	switch requestType {
	case versionApi:
		glog.V(4).Infof("Api - Version")
		versionInfo, err := m.GetVersionInfo()
		if err != nil {
			return err
		}
		return writeResult(versionInfo.CadvisorVersion, w)
	case attributesApi:
		glog.V(4).Info("Api - Attributes")

		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}
		versionInfo, err := m.GetVersionInfo()
		if err != nil {
			return err
		}
		info := v2.GetAttributes(machineInfo, versionInfo)
		return writeResult(info, w)
	case machineApi:
		glog.V(4).Info("Api - Machine")

		// TODO(rjnagal): Move machineInfo from v1.
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}
		return writeResult(machineInfo, w)
	case summaryApi:
		containerName := getContainerName(request)
		glog.V(4).Infof("Api - Summary for container %q, options %+v", containerName, opt)

		stats, err := m.GetDerivedStats(containerName, opt)
		if err != nil {
			return err
		}
		return writeResult(stats, w)
	case statsApi:
		name := getContainerName(request)
		glog.V(4).Infof("Api - Stats: Looking for stats for container %q, options %+v", name, opt)
		conts, err := m.GetRequestedContainersInfo(name, opt)
		if err != nil {
			return err
		}
		contStats := make(map[string][]v2.ContainerStats, 0)
		for name, cont := range conts {
			contStats[name] = convertStats(cont)
		}
		return writeResult(contStats, w)
	case specApi:
		containerName := getContainerName(request)
		glog.V(4).Infof("Api - Spec for container %q, options %+v", containerName, opt)
		specs, err := m.GetContainerSpec(containerName, opt)
		if err != nil {
			return err
		}
		return writeResult(specs, w)
	case storageApi:
		var err error
		fi := []v2.FsInfo{}
		label := r.URL.Query().Get("label")
		if len(label) == 0 {
			// Get all global filesystems info.
			fi, err = m.GetFsInfo("")
			if err != nil {
				return err
			}
		} else {
			// Get a specific label.
			fi, err = m.GetFsInfo(label)
			if err != nil {
				return err
			}
		}
		return writeResult(fi, w)
	case eventsApi:
		return handleEventRequest(request, m, w, r)
	default:
		return fmt.Errorf("unknown request type %q", requestType)
	}
}
Example #11
0
func HandleRequest(m manager.Manager, w http.ResponseWriter, r *http.Request) error {
	start := time.Now()

	u := r.URL

	// Get API request type.
	requestType := u.Path[len(ApiResource):]
	i := strings.Index(requestType, "/")
	requestArgs := ""
	if i != -1 {
		requestArgs = requestType[i:]
		requestType = requestType[:i]
	}

	switch {
	case requestType == MachineApi:
		log.Printf("Api - Machine")

		// Get the MachineInfo
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}

		out, err := json.Marshal(machineInfo)
		if err != nil {
			fmt.Fprintf(w, "Failed to marshall MachineInfo with error: %s", err)
		}
		w.Write(out)
	case requestType == ContainersApi:
		// The container name is the path after the requestType
		containerName := requestArgs

		log.Printf("Api - Container(%s)", containerName)

		var query info.ContainerInfoRequest

		// If a user does not specify number of stats/samples he wants,
		// it's 64 by default
		query.NumStats = 64
		query.NumSamples = 64
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&query)
		if err != nil && err != io.EOF {
			return fmt.Errorf("unable to decode the json value: ", err)
		}
		// Get the container.
		cont, err := m.GetContainerInfo(containerName, &query)
		if err != nil {
			fmt.Fprintf(w, "Failed to get container \"%s\" with error: %s", containerName, err)
			return err
		}

		// Only output the container as JSON.
		out, err := json.Marshal(cont)
		if err != nil {
			fmt.Fprintf(w, "Failed to marshall container %q with error: %s", containerName, err)
		}
		w.Write(out)
	default:
		return fmt.Errorf("unknown API request type %q", requestType)
	}

	log.Printf("Request took %s", time.Since(start))
	return nil
}