
This patch ports the Datastore and DatastorePath objects which have been approved in Nova and will be useful in Glance. Finally, it adds the units module from oslo-incubator. Change-Id: Ia519a83ed09fde74be376981f89284af20aa1dab
166 lines
5.4 KiB
Python
166 lines
5.4 KiB
Python
# Copyright (c) 2014 VMware, Inc.
|
|
#
|
|
# 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.
|
|
|
|
import posixpath
|
|
|
|
from oslo.vmware.openstack.common.gettextutils import _
|
|
|
|
|
|
class Datastore(object):
|
|
|
|
def __init__(self, ref, name, capacity=None, freespace=None):
|
|
"""Datastore object holds ref and name together for convenience.
|
|
|
|
:param ref: a vSphere reference to a datastore
|
|
:param name: vSphere unique name for this datastore
|
|
:param capacity: (optional) capacity in bytes of this datastore
|
|
:param freespace: (optional) free space in bytes of datastore
|
|
"""
|
|
if name is None:
|
|
raise ValueError(_("Datastore name cannot be None"))
|
|
if ref is None:
|
|
raise ValueError(_("Datastore reference cannot be None"))
|
|
if freespace is not None and capacity is None:
|
|
raise ValueError(_("Invalid capacity"))
|
|
if capacity is not None and freespace is not None:
|
|
if capacity < freespace:
|
|
raise ValueError(_("Capacity is smaller than free space"))
|
|
|
|
self._ref = ref
|
|
self._name = name
|
|
self._capacity = capacity
|
|
self._freespace = freespace
|
|
|
|
@property
|
|
def ref(self):
|
|
return self._ref
|
|
|
|
@property
|
|
def name(self):
|
|
return self._name
|
|
|
|
@property
|
|
def capacity(self):
|
|
return self._capacity
|
|
|
|
@property
|
|
def freespace(self):
|
|
return self._freespace
|
|
|
|
def build_path(self, *paths):
|
|
"""Constructs and returns a DatastorePath.
|
|
|
|
:param paths: list of path components, for constructing a path relative
|
|
to the root directory of the datastore
|
|
:return: a DatastorePath object
|
|
"""
|
|
return DatastorePath(self._name, *paths)
|
|
|
|
def __str__(self):
|
|
return '[%s]' % self._name
|
|
|
|
|
|
class DatastorePath(object):
|
|
|
|
"""Class for representing a directory or file path in a vSphere datatore.
|
|
|
|
This provides various helper methods to access components and useful
|
|
variants of the datastore path.
|
|
|
|
Example usage:
|
|
|
|
DatastorePath("datastore1", "_base/foo", "foo.vmdk") creates an
|
|
object that describes the "[datastore1] _base/foo/foo.vmdk" datastore
|
|
file path to a virtual disk.
|
|
|
|
Note:
|
|
- Datastore path representations always uses forward slash as separator
|
|
(hence the use of the posixpath module).
|
|
- Datastore names are enclosed in square brackets.
|
|
- Path part of datastore path is relative to the root directory
|
|
of the datastore, and is always separated from the [ds_name] part with
|
|
a single space.
|
|
"""
|
|
|
|
def __init__(self, datastore_name, *paths):
|
|
if datastore_name is None or datastore_name == '':
|
|
raise ValueError(_("Datastore name cannot be empty"))
|
|
self._datastore_name = datastore_name
|
|
self._rel_path = ''
|
|
if paths:
|
|
if None in paths:
|
|
raise ValueError(_("Path component cannot be None"))
|
|
self._rel_path = posixpath.join(*paths)
|
|
|
|
def __str__(self):
|
|
"""Full datastore path to the file or directory."""
|
|
if self._rel_path != '':
|
|
return "[%s] %s" % (self._datastore_name, self.rel_path)
|
|
return "[%s]" % self._datastore_name
|
|
|
|
@property
|
|
def datastore(self):
|
|
return self._datastore_name
|
|
|
|
@property
|
|
def parent(self):
|
|
return DatastorePath(self.datastore, posixpath.dirname(self._rel_path))
|
|
|
|
@property
|
|
def basename(self):
|
|
return posixpath.basename(self._rel_path)
|
|
|
|
@property
|
|
def dirname(self):
|
|
return posixpath.dirname(self._rel_path)
|
|
|
|
@property
|
|
def rel_path(self):
|
|
return self._rel_path
|
|
|
|
def join(self, *paths):
|
|
"""Join one or more path components intelligently into a datastore path.
|
|
|
|
If any component is an absolute path, all previous components are
|
|
thrown away, and joining continues. The return value is the
|
|
concatenation of the paths with exactly one slash ('/') inserted
|
|
between components, unless p is empty.
|
|
|
|
:return: A datastore path
|
|
"""
|
|
if paths:
|
|
if None in paths:
|
|
raise ValueError(_("Path component cannot be None"))
|
|
return DatastorePath(self.datastore, self._rel_path, *paths)
|
|
return self
|
|
|
|
def __eq__(self, other):
|
|
return (isinstance(other, DatastorePath) and
|
|
self._datastore_name == other._datastore_name and
|
|
self._rel_path == other._rel_path)
|
|
|
|
@classmethod
|
|
def parse(cls, datastore_path):
|
|
"""Constructs a DatastorePath object given a datastore path string."""
|
|
if not datastore_path:
|
|
raise ValueError(_("Datastore path cannot be empty"))
|
|
|
|
spl = datastore_path.split('[', 1)[1].split(']', 1)
|
|
path = ""
|
|
if len(spl) == 1:
|
|
datastore_name = spl[0]
|
|
else:
|
|
datastore_name, path = spl
|
|
return cls(datastore_name, path.strip())
|