resource/lvm/lowlevel/query.go
// Copyright © 2016 Asteris, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package lowlevel
import (
"fmt"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"strings"
)
func (lvm *realLVM) Blkid(dev string) (string, error) {
if ok, err := lvm.backend.Exists(dev); err != nil || !ok {
return "", errors.Wrapf(err, "check for device")
}
blkid, rc, err := lvm.backend.ReadWithExitCode("blkid", []string{"-c", "/dev/null", "-o", "value", "-s", "TYPE", dev})
if err != nil {
return "", err
}
// excerpt from `man blkid`:
// RETURN CODE
// If the specified device or device addressed by specified token (option -t) was found and it's possible to gather any information about the device, an exit code 0 is returned.
// Note the option -s filters output tags, but it does not affect return code.
// If the specified token was not found, or no (specified) devices could be identified, an exit code of 2 is returned.
// For usage or other errors, an exit code of 4 is returned.
// If an ambivalent low-level probing result was detected, an exit code of 8 is returned.
if rc != 2 && rc != 0 {
return blkid, fmt.Errorf("blkid terminated with rc == %d, and output `%s`", rc, blkid)
}
return blkid, nil
}
func (lvm *realLVM) QueryDeviceMapperName(dmName string) (string, error) {
out, err := lvm.backend.Read("dmsetup", []string{"info", "-C", "--noheadings", "-o", "name", dmName})
if err != nil {
return "", errors.Wrapf(err, "query devicemapper")
}
return fmt.Sprintf("/dev/mapper/%s", out), nil
}
func (lvm *realLVM) Query(prog string, out string, extras []string) ([]map[string]interface{}, error) {
result := []map[string]interface{}{}
args := []string{"--nameprefix", "--noheadings", "--unquoted", "--units", "b", "-o", out, "--separator", ";"}
args = append(args, extras...)
output, err := lvm.backend.Read(prog, args)
if err != nil {
return nil, errors.Wrapf(err, "querying %s", prog)
}
for _, line := range strings.Split(output, "\n") {
values := map[string]interface{}{}
for _, field := range strings.Split(line, ";") {
parts := strings.Split(field, "=")
if len(parts) == 1 {
continue
}
values[parts[0]] = parts[1]
}
if len(values) > 0 {
result = append(result, values)
}
}
return result, nil
}
func (lvm *realLVM) parse(values interface{}, dest interface{}) error {
return mapstructure.Decode(values, dest)
}