Example #1
0
    def create(self, parent_group_id, ip_protocol=None, from_port=None,
               to_port=None, cidr=None, group_id=None):
        """
        Create a security group rule

        :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp'
        :param from_port: Source port
        :param to_port: Destination port
        :param cidr: Destination IP address(es) in CIDR notation
        :param group_id: Security group id (int)
        :param parent_group_id: Parent security group id (int)
        """

        try:
            from_port = int(from_port)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("From port must be an integer."))
        try:
            to_port = int(to_port)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("To port must be an integer."))
        if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']:
            raise exceptions.CommandError(_("IP protocol must be 'tcp', 'udp'"
                                            ", or 'icmp'."))

        body = {"security_group_rule": {
            "ip_protocol": ip_protocol,
            "from_port": from_port,
            "to_port": to_port,
            "cidr": cidr,
            "group_id": group_id,
            "parent_group_id": parent_group_id}}

        return self._create('/os-security-group-rules', body,
                            'security_group_rule')
Example #2
0
    def create(self, ip_protocol=None, from_port=None, to_port=None,
               cidr=None):
        """
        Create a security group default rule

        :param ip_protocol: IP protocol, one of 'tcp', 'udp' or 'icmp'
        :param from_port: Source port
        :param to_port: Destination port
        :param cidr: Destination IP address(es) in CIDR notation
        """

        try:
            from_port = int(from_port)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("From port must be an integer."))
        try:
            to_port = int(to_port)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("To port must be an integer."))
        if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']:
            raise exceptions.CommandError(_("IP protocol must be 'tcp', 'udp'"
                                            ", or 'icmp'."))

        body = {"security_group_default_rule": {
            "ip_protocol": ip_protocol,
            "from_port": from_port,
            "to_port": to_port,
            "cidr": cidr}}

        return self._create('/os-security-group-default-rules', body,
                            'security_group_default_rule')
Example #3
0
def do_cell_capacities(cs, args):
    """Get cell capacities for all cells or a given cell."""
    cell = cs.cells.capacities(args.cell)
    print(_("Ram Available: %s MB") % cell.capacities['ram_free']['total_mb'])
    utils.print_dict(cell.capacities['ram_free']['units_by_mb'],
                     dict_property='Ram(MB)', dict_value="Units")
    print(_("\nDisk Available: %s MB") %
          cell.capacities['disk_free']['total_mb'])
    utils.print_dict(cell.capacities['disk_free']['units_by_mb'],
                     dict_property='Disk(MB)', dict_value="Units")
Example #4
0
def positive_non_zero_float(text):
    if text is None:
        return None
    try:
        value = float(text)
    except ValueError:
        msg = _("%s must be a float") % text
        raise argparse.ArgumentTypeError(msg)
    if value <= 0:
        msg = _("%s must be greater than 0") % text
        raise argparse.ArgumentTypeError(msg)
    return value
Example #5
0
def positive_non_zero_float(text):
    if text is None:
        return None
    try:
        value = float(text)
    except ValueError:
        msg = _("%s must be a float") % text
        raise argparse.ArgumentTypeError(msg)
    if value <= 0:
        msg = _("%s must be greater than 0") % text
        raise argparse.ArgumentTypeError(msg)
    return value
Example #6
0
def find_resource(manager, name_or_id, **find_args):
    """Helper for the _find_* methods."""
    # for str id which is not uuid (for Flavor and Keypair search currently)
    if getattr(manager, 'is_alphanum_id_allowed', False):
        try:
            return manager.get(name_or_id)
        except exceptions.NotFound:
            pass

    # try to get entity as integer id
    try:
        return manager.get(int(name_or_id))
    except (TypeError, ValueError, exceptions.NotFound):
        pass

    # now try to get entity as uuid
    try:
        tmp_id = encodeutils.safe_encode(name_or_id)

        if six.PY3:
            tmp_id = tmp_id.decode()

        uuid.UUID(tmp_id)
        return manager.get(tmp_id)
    except (TypeError, ValueError, exceptions.NotFound):
        pass

    try:
        try:
            resource = getattr(manager, 'resource_class', None)
            name_attr = resource.NAME_ATTR if resource else 'name'
            kwargs = {name_attr: name_or_id}
            kwargs.update(find_args)
            return manager.find(**kwargs)
        except exceptions.NotFound:
            pass

        # finally try to find entity by human_id
        try:
            return manager.find(human_id=name_or_id, **find_args)
        except exceptions.NotFound:
            msg = (_("No %(class)s with a name or ID of '%(name)s' exists.") %
                   {'class': manager.resource_class.__name__.lower(),
                    'name': name_or_id})
            raise exceptions.CommandError(msg)
    except exceptions.NoUniqueMatch:
        msg = (_("Multiple %(class)s matches found for '%(name)s', use an ID "
                 "to be more specific.") %
               {'class': manager.resource_class.__name__.lower(),
                'name': name_or_id})
        raise exceptions.CommandError(msg)
Example #7
0
 def list(self, **kwargs):
     if kwargs.get('flavor'):
         return self._list_by_flavor(kwargs['flavor'])
     elif kwargs.get('tenant'):
         return self._list_by_tenant(kwargs['tenant'])
     else:
         raise NotImplementedError(_('Unknown list options.'))
Example #8
0
def validate_flavor_metadata_keys(keys):
    for key in keys:
        valid_name = VALID_KEY_REGEX.match(key)
        if not valid_name:
            msg = _('Invalid key: "%s". Keys may only contain letters, '
                    'numbers, spaces, underscores, periods, colons and '
                    'hyphens.')
            raise exceptions.CommandError(msg % key)
Example #9
0
 def do_help(self, args):
     """
     Display help about this program or one of its subcommands.
     """
     if args.command:
         if args.command in self.subcommands:
             self.subcommands[args.command].print_help()
         else:
             raise exc.CommandError(
                 _("'%s' is not a valid subcommand") % args.command)
     else:
         self.parser.print_help()
Example #10
0
def _server_migrate(cs, server):
    success = True
    error_message = ""
    try:
        cs.servers.migrate(server['uuid'])
    except Exception as e:
        success = False
        error_message = _("Error while migrating instance: %s") % e
    return HostServersMigrateResponse(base.Manager,
                                      {"server_uuid": server['uuid'],
                                       "migration_accepted": success,
                                       "error_message": error_message})
Example #11
0
 def do_help(self, args):
     """
     Display help about this program or one of its subcommands.
     """
     if args.command:
         if args.command in self.subcommands:
             self.subcommands[args.command].print_help()
         else:
             raise exc.CommandError(_("'%s' is not a valid subcommand") %
                                    args.command)
     else:
         self.parser.print_help()
Example #12
0
    def create(self, name, ram, vcpus, disk, flavorid="auto",
               ephemeral=0, swap=0, rxtx_factor=1.0, is_public=True):
        """
        Create a flavor.

        :param name: Descriptive name of the flavor
        :param ram: Memory in MB for the flavor
        :param vcpus: Number of VCPUs for the flavor
        :param disk: Size of local disk in GB
        :param flavorid: ID for the flavor (optional). You can use the reserved
                         value ``"auto"`` to have Patron generate a UUID for the
                         flavor in cases where you cannot simply pass ``None``.
        :param swap: Swap space in MB
        :param rxtx_factor: RX/TX factor
        :rtype: :class:`Flavor`
        """

        try:
            ram = int(ram)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Ram must be an integer."))
        try:
            vcpus = int(vcpus)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("VCPUs must be an integer."))
        try:
            disk = int(disk)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Disk must be an integer."))

        if flavorid == "auto":
            flavorid = None

        try:
            swap = int(swap)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Swap must be an integer."))
        try:
            ephemeral = int(ephemeral)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Ephemeral must be an integer."))
        try:
            rxtx_factor = float(rxtx_factor)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("rxtx_factor must be a float."))

        try:
            is_public = strutils.bool_from_string(is_public, True)
        except Exception:
            raise exceptions.CommandError(_("is_public must be a boolean."))

        body = self._build_body(name, ram, vcpus, disk, flavorid, swap,
                                ephemeral, rxtx_factor, is_public)

        return self._create("/flavors", body, "flavor")
Example #13
0
    def _extract_service_catalog(self, url, resp, body, extract_token=True):
        """See what the auth service told us and process the response.
        We may get redirected to another site, fail or actually get
        back a service catalog with a token and our endpoints.
        """

        # content must always present
        if resp.status_code == 200 or resp.status_code == 201:
            try:
                self.auth_url = url
                self.service_catalog = \
                    service_catalog.ServiceCatalog(body)
                if extract_token:
                    self.auth_token = self.service_catalog.get_token()
                    self.tenant_id = self.service_catalog.get_tenant_id()

                management_url = self.service_catalog.url_for(
                    attr='region',
                    filter_value=self.region_name,
                    endpoint_type=self.endpoint_type,
                    service_type=self.service_type,
                    service_name=self.service_name,
                    volume_service_name=self.volume_service_name,)
                self.management_url = management_url.rstrip('/')
                return None
            except exceptions.AmbiguousEndpoints:
                print(_("Found more than one valid endpoint. Use a more "
                      "restrictive filter"))
                raise
            except KeyError:
                raise exceptions.AuthorizationFailure()
            except exceptions.EndpointNotFound:
                print(_("Could not find any suitable endpoint. Correct "
                        "region?"))
                raise

        elif resp.status_code == 305:
            return resp.headers['location']
        else:
            raise exceptions.from_response(resp, body, url)
Example #14
0
def _server_evacuate(cs, server, args):
    success = True
    error_message = ""
    try:
        cs.servers.evacuate(server=server['uuid'], host=args.target_host,
                            on_shared_storage=args.on_shared_storage)
    except Exception as e:
        success = False
        error_message = _("Error while evacuating instance: %s") % e
    return EvacuateHostResponse(base.Manager,
                                {"server_uuid": server['uuid'],
                                 "evacuate_accepted": success,
                                 "error_message": error_message})
Example #15
0
 def save(self, auth_token, management_url, tenant_id):
     if not HAS_KEYRING or not self.args.os_cache:
         return
     if (auth_token == self.auth_token and
             management_url == self.management_url):
         # Nothing changed....
         return
     if not all([management_url, auth_token, tenant_id]):
         raise ValueError(_("Unable to save empty management url/auth "
                            "token"))
     value = "|".join([str(auth_token),
                       str(management_url),
                       str(tenant_id)])
     keyring.set_password("patronclient_auth", self._make_key(), value)
Example #16
0
    def error(self, message):
        """error(message: string)

        Prints a usage message incorporating the message to stderr and
        exits.
        """
        self.print_usage(sys.stderr)
        # FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value
        choose_from = ' (choose from'
        progparts = self.prog.partition(' ')
        self.exit(2, _("error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'"
                       " for more information.\n") %
                  {'errmsg': message.split(choose_from)[0],
                   'mainp': progparts[0],
                   'subp': progparts[2]})
Example #17
0
def get_client_class(version):
    version_map = {
        '1.1': 'patronclient.v2.client.Client',
        '2': 'patronclient.v2.client.Client',
        '3': 'patronclient.v2.client.Client',
    }
    try:
        client_path = version_map[str(version)]
    except (KeyError, ValueError):
        msg = _("Invalid client version '%(version)s'. must be one of: "
                "%(keys)s") % {'version': version,
                               'keys': ', '.join(version_map.keys())}
        raise exceptions.UnsupportedVersion(msg)

    return importutils.import_class(client_path)
Example #18
0
 def save(self, auth_token, management_url, tenant_id):
     if not HAS_KEYRING or not self.args.os_cache:
         return
     if (auth_token == self.auth_token
             and management_url == self.management_url):
         # Nothing changed....
         return
     if not all([management_url, auth_token, tenant_id]):
         raise ValueError(
             _("Unable to save empty management url/auth "
               "token"))
     value = "|".join(
         [str(auth_token),
          str(management_url),
          str(tenant_id)])
     keyring.set_password("patronclient_auth", self._make_key(), value)
Example #19
0
def _server_evacuate(cs, server, args):
    success = True
    error_message = ""
    try:
        cs.servers.evacuate(server=server['uuid'],
                            host=args.target_host,
                            on_shared_storage=args.on_shared_storage)
    except Exception as e:
        success = False
        error_message = _("Error while evacuating instance: %s") % e
    return EvacuateHostResponse(
        base.Manager, {
            "server_uuid": server['uuid'],
            "evacuate_accepted": success,
            "error_message": error_message
        })
Example #20
0
def _server_live_migrate(cs, server, args):
    class HostEvacuateLiveResponse(object):
        def __init__(self, server_uuid, live_migration_accepted,
                     error_message):
            self.server_uuid = server_uuid
            self.live_migration_accepted = live_migration_accepted
            self.error_message = error_message

    success = True
    error_message = ""
    try:
        cs.servers.live_migrate(server['uuid'], args.target_host,
                                args.block_migrate, args.disk_over_commit)
    except Exception as e:
        success = False
        error_message = _("Error while live migrating instance: %s") % e
    return HostEvacuateLiveResponse(server['uuid'], success, error_message)
Example #21
0
    def error(self, message):
        """error(message: string)

        Prints a usage message incorporating the message to stderr and
        exits.
        """
        self.print_usage(sys.stderr)
        # FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value
        choose_from = ' (choose from'
        progparts = self.prog.partition(' ')
        self.exit(
            2,
            _("error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'"
              " for more information.\n") % {
                  'errmsg': message.split(choose_from)[0],
                  'mainp': progparts[0],
                  'subp': progparts[2]
              })
Example #22
0
def _server_live_migrate(cs, server, args):
    class HostEvacuateLiveResponse(object):
        def __init__(self, server_uuid, live_migration_accepted,
                     error_message):
            self.server_uuid = server_uuid
            self.live_migration_accepted = live_migration_accepted
            self.error_message = error_message
    success = True
    error_message = ""
    try:
        cs.servers.live_migrate(server['uuid'], args.target_host,
                                args.block_migrate, args.disk_over_commit)
    except Exception as e:
        success = False
        error_message = _("Error while live migrating instance: %s") % e
    return HostEvacuateLiveResponse(server['uuid'],
                                    success,
                                    error_message)
Example #23
0
def get_resource_manager_extra_kwargs(f, args, allow_conflicts=False):
    """Return extra_kwargs by calling resource manager kwargs hooks."""
    hooks = getattr(f, "resource_manager_kwargs_hooks", [])
    extra_kwargs = {}
    for hook in hooks:
        hook_kwargs = hook(args)
        hook_name = hook.__name__
        conflicting_keys = set(hook_kwargs.keys()) & set(extra_kwargs.keys())
        if conflicting_keys and not allow_conflicts:
            msg = (_("Hook '%(hook_name)s' is attempting to redefine "
                     "attributes '%(conflicting_keys)s'") %
                   {'hook_name': hook_name,
                    'conflicting_keys': conflicting_keys})
            raise exceptions.NoUniqueMatch(msg)

        extra_kwargs.update(hook_kwargs)

    return extra_kwargs
Example #24
0
    def disassociate(self,
                     network,
                     disassociate_host=True,
                     disassociate_project=True):
        """
        Disassociate a specific network from project and/or host.

        :param network: The ID of the :class:`Network`.
        :param disassociate_host: Whether to disassociate the host
        :param disassociate_project: Whether to disassociate the project
        """
        if disassociate_host and disassociate_project:
            body = {"disassociate": None}
        elif disassociate_project:
            body = {"disassociate_project": None}
        elif disassociate_host:
            body = {"disassociate_host": None}
        else:
            raise exceptions.CommandError(
                _("Must disassociate either host or project or both"))

        self.api.client.post("/os-networks/%s/action" % base.getid(network),
                             body=body)
Example #25
0
        patron setpolicy
        """
        return self.api.client.post("/os-patron-access/setlabel", **kwargs)


    def getlabel(self, **kwargs):
        """
        patron setpolicy
        """
        return self.api.client.get("/os-patron-access/getlabel", **kwargs)


@cliutils.arg(
    '--op',
    metavar='<op>',
    help=_('User op for example:\n\tcompute_extension:admin_actions'))
def do_verify(cs, args):
    """patron verify. Args:op. For example:\n\tcompute_extension:admin_actions"""
    ans = cs.patron_access.verify(json = {'op': args.op})
    print ans

@cliutils.arg(
    '--file',
    metavar='<file>',
    help=_('User policy file path'))
def do_setpolicy(cs, args):
    """patron setpolicy. Args:policy."""
    #check file exists?
    if os.path.exists(args.file) and os.path.isfile(args.file) :
        policy = open(args.file, 'r')
        obj = dict(json.loads(policy.read()))
Example #26
0
 def _list_by_tenant(self, tenant):
     """Print flavor list shared with the given tenant."""
     # TODO(uni): need to figure out a proper URI for list_by_tenant
     # since current API already provided current tenant_id information
     raise NotImplementedError(_('Sorry, query by tenant not supported.'))
Example #27
0
    def setlabel(self, **kwargs):
        """
        patron setpolicy
        """
        return self.api.client.post("/os-patron-access/setlabel", **kwargs)

    def getlabel(self, **kwargs):
        """
        patron setpolicy
        """
        return self.api.client.get("/os-patron-access/getlabel", **kwargs)


@cliutils.arg('--op',
              metavar='<op>',
              help=_('User op for example:\n\tcompute_extension:admin_actions')
              )
def do_verify(cs, args):
    """patron verify. Args:op. For example:\n\tcompute_extension:admin_actions"""
    ans = cs.patron_access.verify(json={'op': args.op})
    print ans


@cliutils.arg('--file', metavar='<file>', help=_('User policy file path'))
def do_setpolicy(cs, args):
    """patron setpolicy. Args:policy."""
    #check file exists?
    if os.path.exists(args.file) and os.path.isfile(args.file):
        policy = open(args.file, 'r')
        obj = dict(json.loads(policy.read()))
        ans = cs.patron_access.setpolicy(json={'policy': obj})
Example #28
0
    def create(self,
               name,
               ram,
               vcpus,
               disk,
               flavorid="auto",
               ephemeral=0,
               swap=0,
               rxtx_factor=1.0,
               is_public=True):
        """
        Create a flavor.

        :param name: Descriptive name of the flavor
        :param ram: Memory in MB for the flavor
        :param vcpus: Number of VCPUs for the flavor
        :param disk: Size of local disk in GB
        :param flavorid: ID for the flavor (optional). You can use the reserved
                         value ``"auto"`` to have Patron generate a UUID for the
                         flavor in cases where you cannot simply pass ``None``.
        :param swap: Swap space in MB
        :param rxtx_factor: RX/TX factor
        :rtype: :class:`Flavor`
        """

        try:
            ram = int(ram)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Ram must be an integer."))
        try:
            vcpus = int(vcpus)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("VCPUs must be an integer."))
        try:
            disk = int(disk)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Disk must be an integer."))

        if flavorid == "auto":
            flavorid = None

        try:
            swap = int(swap)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Swap must be an integer."))
        try:
            ephemeral = int(ephemeral)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("Ephemeral must be an integer."))
        try:
            rxtx_factor = float(rxtx_factor)
        except (TypeError, ValueError):
            raise exceptions.CommandError(_("rxtx_factor must be a float."))

        try:
            is_public = strutils.bool_from_string(is_public, True)
        except Exception:
            raise exceptions.CommandError(_("is_public must be a boolean."))

        body = self._build_body(name, ram, vcpus, disk, flavorid, swap,
                                ephemeral, rxtx_factor, is_public)

        return self._create("/flavors", body, "flavor")
Example #29
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.

from patronclient.i18n import _
from patronclient.openstack.common import cliutils
from patronclient.v2 import shell


@cliutils.arg(
    'host',
    metavar='<host>',
    help=_('Name of host.'))
@cliutils.arg(
    'action',
    metavar='<action>',
    choices=['set', 'delete'],
    help=_("Actions: 'set' or 'delete'"))
@cliutils.arg(
    'metadata',
    metavar='<key=value>',
    nargs='+',
    action='append',
    default=[],
    help=_('Metadata to set or delete (only key is necessary on delete)'))
def do_host_meta(cs, args):
    """Set or Delete metadata on all instances of a host."""
    hypervisors = cs.hypervisors.search(args.host, servers=True)
Example #30
0
        """
        return self._get("/servers/%s/os-instance-actions/%s" %
                         (base.getid(server), request_id), 'instanceAction')

    def list(self, server):
        """
        Get a list of actions performed on an server.
        """
        return self._list('/servers/%s/os-instance-actions' %
                          base.getid(server), 'instanceActions')


@cliutils.arg(
    'server',
    metavar='<server>',
    help=_('Name or UUID of the server to show an action for.'))
@cliutils.arg(
    'request_id',
    metavar='<request_id>',
    help=_('Request ID of the action to get.'))
def do_instance_action(cs, args):
    """Show an action."""
    server = utils.find_resource(cs.servers, args.server)
    action_resource = cs.instance_action.get(server, args.request_id)
    action = action_resource._info
    if 'events' in action:
        action['events'] = pprint.pformat(action['events'])
    utils.print_dict(action)


@cliutils.arg(
Example #31
0
        return self._get(
            "/servers/%s/os-instance-actions/%s" %
            (base.getid(server), request_id), 'instanceAction')

    def list(self, server):
        """
        Get a list of actions performed on an server.
        """
        return self._list(
            '/servers/%s/os-instance-actions' % base.getid(server),
            'instanceActions')


@cliutils.arg('server',
              metavar='<server>',
              help=_('Name or UUID of the server to show an action for.'))
@cliutils.arg('request_id',
              metavar='<request_id>',
              help=_('Request ID of the action to get.'))
def do_instance_action(cs, args):
    """Show an action."""
    server = utils.find_resource(cs.servers, args.server)
    action_resource = cs.instance_action.get(server, args.request_id)
    action = action_resource._info
    if 'events' in action:
        action['events'] = pprint.pformat(action['events'])
    utils.print_dict(action)


@cliutils.arg('server',
              metavar='<server>',
Example #32
0
            opts['cell_name'] = cell_name

        # Transform the dict to a sequence of two-element tuples in fixed
        # order, then the encoded string will be consistent in Python 2&3.
        new_opts = sorted(opts.items(), key=lambda x: x[0])

        query_string = "?%s" % parse.urlencode(new_opts) if new_opts else ""

        return self._list("/os-migrations%s" % query_string, "migrations")


@cliutils.arg(
    '--host',
    dest='host',
    metavar='<host>',
    help=_('Fetch migrations for the given host.'))
@cliutils.arg(
    '--status',
    dest='status',
    metavar='<status>',
    help=_('Fetch migrations for the given status.'))
@cliutils.arg(
    '--cell_name',
    dest='cell_name',
    metavar='<cell_name>',
    help=_('Fetch migrations for the given cell_name.'))
def do_migration_list(cs, args):
    """Print a list of migrations."""
    _print_migrations(cs.migrations.list(args.host, args.status,
                                         args.cell_name))
Example #33
0
    def capacities(self, cell_name=None):
        """
        Get capacities for a cell.

        :param cell_name: Name of the :class:`Cell` to get capacities for.
        :rtype: :class:`Cell`
        """
        path = ["%s/capacities" % cell_name, "capacities"][cell_name is None]
        return self._get("/os-cells/%s" % path, "cell")


@cliutils.arg(
    'cell',
    metavar='<cell-name>',
    help=_('Name of the cell.'))
def do_cell_show(cs, args):
    """Show details of a given cell."""
    cell = cs.cells.get(args.cell)
    utils.print_dict(cell._info)


@cliutils.arg(
    '--cell',
    metavar='<cell-name>',
    help=_("Name of the cell to get the capacities."),
    default=None)
def do_cell_capacities(cs, args):
    """Get cell capacities for all cells or a given cell."""
    cell = cs.cells.capacities(args.cell)
    print(_("Ram Available: %s MB") % cell.capacities['ram_free']['total_mb'])
Example #34
0
def do_net_list(cs, args):
    """
    DEPRECATED, use tenant-network-list instead.
    """
    do_tenant_network_list(cs, args)


def do_tenant_network_list(cs, args):
    """
    List tenant networks.
    """
    networks = cs.tenant_networks.list()
    utils.print_list(networks, ["ID", "Label", "CIDR"])


@cliutils.arg("label", metavar="<network_label>", help=_("Network label (ex. my_new_network)"))
@cliutils.arg("cidr", metavar="<cidr>", help=_("IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)"))
def do_net_create(cs, args):
    """
    DEPRECATED, use tenant-network-create instead.
    """
    do_tenant_network_create(cs, args)


@cliutils.arg("label", metavar="<network_label>", help=_("Network label (ex. my_new_network)"))
@cliutils.arg("cidr", metavar="<cidr>", help=_("IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)"))
def do_tenant_network_create(cs, args):
    """
    Create a tenant network.
    """
    network = cs.tenant_networks.create(args.label, args.cidr)
Example #35
0
        cs.servers.live_migrate(server['uuid'], args.target_host,
                                args.block_migrate, args.disk_over_commit)
    except Exception as e:
        success = False
        error_message = _("Error while live migrating instance: %s") % e
    return HostEvacuateLiveResponse(server['uuid'],
                                    success,
                                    error_message)


@cliutils.arg('host', metavar='<host>', help='Name of host.')
@cliutils.arg(
    '--target-host',
    metavar='<target_host>',
    default=None,
    help=_('Name of target host.'))
@cliutils.arg(
    '--block-migrate',
    action='store_true',
    default=False,
    help=_('Enable block migration.'))
@cliutils.arg(
    '--disk-over-commit',
    action='store_true',
    default=False,
    help=_('Enable disk overcommit.'))
def do_host_evacuate_live(cs, args):
    """Live migrate all instances of the specified host
    to other available hosts.
    """
    hypervisors = cs.hypervisors.search(args.host, servers=True)
Example #36
0
    def authenticate(self):
        if not self.auth_url:
            msg = _("Authentication requires 'auth_url', which should be "
                    "specified in '%s'") % self.__class__.__name__
            raise exceptions.AuthorizationFailure(msg)
        magic_tuple = netutils.urlsplit(self.auth_url)
        scheme, netloc, path, query, frag = magic_tuple
        port = magic_tuple.port
        if port is None:
            port = 80
        path_parts = path.split('/')
        for part in path_parts:
            if len(part) > 0 and part[0] == 'v':
                self.version = part
                break

        if self.auth_token and self.management_url:
            self._save_keys()
            return

        # TODO(sandy): Assume admin endpoint is 35357 for now.
        # Ideally this is going to have to be provided by the service catalog.
        new_netloc = netloc.replace(':%d' % port, ':%d' % (35357,))
        admin_url = parse.urlunsplit(
            (scheme, new_netloc, path, query, frag))

        auth_url = self.auth_url
        if self.version == "v2.0":  # FIXME(chris): This should be better.
            while auth_url:
                if not self.auth_system or self.auth_system == 'keystone':
                    auth_url = self._v2_auth(auth_url)
                else:
                    auth_url = self._plugin_auth(auth_url)

            # Are we acting on behalf of another user via an
            # existing token? If so, our actual endpoints may
            # be different than that of the admin token.
            if self.proxy_token:
                if self.bypass_url:
                    self.set_management_url(self.bypass_url)
                else:
                    self._fetch_endpoints_from_auth(admin_url)
                # Since keystone no longer returns the user token
                # with the endpoints any more, we need to replace
                # our service account token with the user token.
                self.auth_token = self.proxy_token
        else:
            try:
                while auth_url:
                    auth_url = self._v1_auth(auth_url)
            # In some configurations patron makes redirection to
            # v2.0 keystone endpoint. Also, new location does not contain
            # real endpoint, only hostname and port.
            except exceptions.AuthorizationFailure:
                if auth_url.find('v2.0') < 0:
                    auth_url = auth_url + '/v2.0'
                self._v2_auth(auth_url)

        if self.bypass_url:
            self.set_management_url(self.bypass_url)
        elif not self.management_url:
            raise exceptions.Unauthorized('Patron Client')

        self._save_keys()
Example #37
0
    def _boot(self,
              resource_url,
              response_key,
              name,
              image,
              flavor,
              meta=None,
              files=None,
              userdata=None,
              reservation_id=None,
              return_raw=False,
              min_count=None,
              max_count=None,
              security_groups=None,
              key_name=None,
              availability_zone=None,
              block_device_mapping=None,
              block_device_mapping_v2=None,
              nics=None,
              scheduler_hints=None,
              config_drive=None,
              admin_pass=None,
              disk_config=None,
              **kwargs):
        """
        Create (boot) a new server.

        :param name: Something to name the server.
        :param image: The :class:`Image` to boot with.
        :param flavor: The :class:`Flavor` to boot onto.
        :param meta: A dict of arbitrary key/value metadata to store for this
                     server. A maximum of five entries is allowed, and both
                     keys and values must be 255 characters or less.
        :param files: A dict of files to overwrite on the server upon boot.
                      Keys are file names (i.e. ``/etc/passwd``) and values
                      are the file contents (either as a string or as a
                      file-like object). A maximum of five entries is allowed,
                      and each file must be 10k or less.
        :param reservation_id: a UUID for the set of servers being requested.
        :param return_raw: If True, don't try to coerce the result into
                           a Resource object.
        :param security_groups: list of security group names
        :param key_name: (optional extension) name of keypair to inject into
                         the instance
        :param availability_zone: Name of the availability zone for instance
                                  placement.
        :param block_device_mapping: A dict of block device mappings for this
                                     server.
        :param block_device_mapping_v2: A dict of block device mappings V2 for
                                        this server.
        :param nics:  (optional extension) an ordered list of nics to be
                      added to this server, with information about
                      connected networks, fixed IPs, etc.
        :param scheduler_hints: (optional extension) arbitrary key-value pairs
                              specified by the client to help boot an instance.
        :param config_drive: (optional extension) If True, enable config drive
                             on the server.
        :param admin_pass: admin password for the server.
        :param disk_config: (optional extension) control how the disk is
                            partitioned when the server is created.
        """
        body = {
            "server": {
                "name": name,
                "imageRef": str(base.getid(image)) if image else '',
                "flavorRef": str(base.getid(flavor)),
            }
        }
        if userdata:
            if hasattr(userdata, 'read'):
                userdata = userdata.read()

            if six.PY3:
                userdata = userdata.encode("utf-8")
            else:
                userdata = encodeutils.safe_encode(userdata)

            userdata_b64 = base64.b64encode(userdata).decode('utf-8')
            body["server"]["user_data"] = userdata_b64
        if meta:
            body["server"]["metadata"] = meta
        if reservation_id:
            body["server"]["reservation_id"] = reservation_id
        if key_name:
            body["server"]["key_name"] = key_name
        if scheduler_hints:
            body['os:scheduler_hints'] = scheduler_hints
        if config_drive:
            body["server"]["config_drive"] = config_drive
        if admin_pass:
            body["server"]["adminPass"] = admin_pass
        if not min_count:
            min_count = 1
        if not max_count:
            max_count = min_count
        body["server"]["min_count"] = min_count
        body["server"]["max_count"] = max_count

        if security_groups:
            body["server"]["security_groups"] = [{
                'name': sg
            } for sg in security_groups]

        # Files are a slight bit tricky. They're passed in a "personality"
        # list to the POST. Each item is a dict giving a file name and the
        # base64-encoded contents of the file. We want to allow passing
        # either an open file *or* some contents as files here.
        if files:
            personality = body['server']['personality'] = []
            for filepath, file_or_string in sorted(files.items(),
                                                   key=lambda x: x[0]):
                if hasattr(file_or_string, 'read'):
                    data = file_or_string.read()
                else:
                    data = file_or_string

                if six.PY3 and isinstance(data, str):
                    data = data.encode('utf-8')
                cont = base64.b64encode(data).decode('utf-8')
                personality.append({
                    'path': filepath,
                    'contents': cont,
                })

        if availability_zone:
            body["server"]["availability_zone"] = availability_zone

        # Block device mappings are passed as a list of dictionaries
        if block_device_mapping:
            body['server']['block_device_mapping'] = \
                self._parse_block_device_mapping(block_device_mapping)
        elif block_device_mapping_v2:
            body['server']['block_device_mapping_v2'] = block_device_mapping_v2

        if nics is not None:
            # NOTE(tr3buchet): nics can be an empty list
            all_net_data = []
            for nic_info in nics:
                net_data = {}
                # if value is empty string, do not send value in body
                if nic_info.get('net-id'):
                    net_data['uuid'] = nic_info['net-id']
                if (nic_info.get('v4-fixed-ip')
                        and nic_info.get('v6-fixed-ip')):
                    raise base.exceptions.CommandError(
                        _("Only one of 'v4-fixed-ip' and 'v6-fixed-ip' may be"
                          " provided."))
                elif nic_info.get('v4-fixed-ip'):
                    net_data['fixed_ip'] = nic_info['v4-fixed-ip']
                elif nic_info.get('v6-fixed-ip'):
                    net_data['fixed_ip'] = nic_info['v6-fixed-ip']
                if nic_info.get('port-id'):
                    net_data['port'] = nic_info['port-id']
                all_net_data.append(net_data)
            body['server']['networks'] = all_net_data

        if disk_config is not None:
            body['server']['OS-DCF:diskConfig'] = disk_config

        return self._create(resource_url,
                            body,
                            response_key,
                            return_raw=return_raw,
                            **kwargs)
Example #38
0
    def main(self, argv):
        # Parse args once to find version and debug settings
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(argv)
        self.setup_debugging(options.debug)

        # Discover available auth plugins
        patronclient.auth_plugin.discover_auth_systems()

        # build available subcommands based on version
        self.extensions = self._discover_extensions(
            options.os_compute_api_version)
        self._run_extension_hooks('__pre_parse_args__')

        # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.
        if '--endpoint_type' in argv:
            spot = argv.index('--endpoint_type')
            argv[spot] = '--endpoint-type'

        subcommand_parser = self.get_subcommand_parser(
            options.os_compute_api_version)
        self.parser = subcommand_parser

        if options.help or not argv:
            subcommand_parser.print_help()
            return 0

        args = subcommand_parser.parse_args(argv)
        self._run_extension_hooks('__post_parse_args__', args)

        # Short-circuit and deal with help right away.
        if args.func == self.do_help:
            self.do_help(args)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        os_username = args.os_username
        os_user_id = args.os_user_id
        os_password = None  # Fetched and set later as needed
        os_tenant_name = args.os_tenant_name
        os_tenant_id = args.os_tenant_id
        os_auth_url = args.os_auth_url
        os_region_name = args.os_region_name
        os_auth_system = args.os_auth_system
        endpoint_type = args.endpoint_type
        insecure = args.insecure
        service_type = args.service_type
        service_name = args.service_name
        volume_service_name = args.volume_service_name
        bypass_url = args.bypass_url
        os_cache = args.os_cache
        cacert = args.os_cacert
        timeout = args.timeout

        keystone_session = None
        keystone_auth = None

        # We may have either, both or none of these.
        # If we have both, we don't need USERNAME, PASSWORD etc.
        # Fill in the blanks from the SecretsHelper if possible.
        # Finally, authenticate unless we have both.
        # Note if we don't auth we probably don't have a tenant ID so we can't
        # cache the token.
        auth_token = args.os_auth_token if args.os_auth_token else None
        management_url = bypass_url if bypass_url else None

        if os_auth_system and os_auth_system != "keystone":
            auth_plugin = patronclient.auth_plugin.load_plugin(os_auth_system)
        else:
            auth_plugin = None

        if not endpoint_type:
            endpoint_type = DEFAULT_PATRON_ENDPOINT_TYPE

        # This allow users to use endpoint_type as (internal, public or admin)
        # just like other openstack clients (glance, cinder etc)
        if endpoint_type in ['internal', 'public', 'admin']:
            endpoint_type += 'URL'

        if not service_type:
            os_compute_api_version = (options.os_compute_api_version
                                      or DEFAULT_OS_COMPUTE_API_VERSION)
            try:
                service_type = DEFAULT_PATRON_SERVICE_TYPE_MAP[
                    os_compute_api_version]
            except KeyError:
                service_type = DEFAULT_PATRON_SERVICE_TYPE_MAP[
                    DEFAULT_OS_COMPUTE_API_VERSION]
            service_type = cliutils.get_service_type(args.func) or service_type

        # If we have an auth token but no management_url, we must auth anyway.
        # Expired tokens are handled by client.py:_cs_request
        must_auth = not (cliutils.isunauthenticated(args.func) or
                         (auth_token and management_url))

        # Do not use Keystone session for cases with no session support. The
        # presence of auth_plugin means os_auth_system is present and is not
        # keystone.
        use_session = True
        if auth_plugin or bypass_url or os_cache or volume_service_name:
            use_session = False

        # FIXME(usrleon): Here should be restrict for project id same as
        # for os_username or os_password but for compatibility it is not.
        if must_auth:
            if auth_plugin:
                auth_plugin.parse_opts(args)

            if not auth_plugin or not auth_plugin.opts:
                if not os_username and not os_user_id:
                    raise exc.CommandError(
                        _("You must provide a username "
                          "or user id via --os-username, --os-user-id, "
                          "env[OS_USERNAME] or env[OS_USER_ID]"))

            if not any([
                    args.os_tenant_name, args.os_tenant_id, args.os_project_id,
                    args.os_project_name
            ]):
                raise exc.CommandError(
                    _("You must provide a project name or"
                      " project id via --os-project-name,"
                      " --os-project-id, env[OS_PROJECT_ID]"
                      " or env[OS_PROJECT_NAME]. You may"
                      " use os-project and os-tenant"
                      " interchangeably."))

            if not os_auth_url:
                if os_auth_system and os_auth_system != 'keystone':
                    os_auth_url = auth_plugin.get_auth_url()

            if not os_auth_url:
                raise exc.CommandError(
                    _("You must provide an auth url "
                      "via either --os-auth-url or env[OS_AUTH_URL] "
                      "or specify an auth_system which defines a "
                      "default url with --os-auth-system "
                      "or env[OS_AUTH_SYSTEM]"))

            project_id = args.os_project_id or args.os_tenant_id
            project_name = args.os_project_name or args.os_tenant_name
            if use_session:
                # Not using Patron auth plugin, so use keystone
                start_time = time.time()
                keystone_session = ksession.Session.load_from_cli_options(args)
                keystone_auth = self._get_keystone_auth(
                    keystone_session,
                    args.os_auth_url,
                    username=args.os_username,
                    user_id=args.os_user_id,
                    user_domain_id=args.os_user_domain_id,
                    user_domain_name=args.os_user_domain_name,
                    password=args.os_password,
                    auth_token=args.os_auth_token,
                    project_id=project_id,
                    project_name=project_name,
                    project_domain_id=args.os_project_domain_id,
                    project_domain_name=args.os_project_domain_name)
                end_time = time.time()
                self.times.append(('%s %s' % ('auth_url', args.os_auth_url),
                                   start_time, end_time))

        if (options.os_compute_api_version
                and options.os_compute_api_version != '1.0'):
            if not any([
                    args.os_tenant_id, args.os_tenant_name, args.os_project_id,
                    args.os_project_name
            ]):
                raise exc.CommandError(
                    _("You must provide a project name or"
                      " project id via --os-project-name,"
                      " --os-project-id, env[OS_PROJECT_ID]"
                      " or env[OS_PROJECT_NAME]. You may"
                      " use os-project and os-tenant"
                      " interchangeably."))

            if not os_auth_url:
                raise exc.CommandError(
                    _("You must provide an auth url "
                      "via either --os-auth-url or env[OS_AUTH_URL]"))

        self.cs = client.Client(options.os_compute_api_version,
                                os_username,
                                os_password,
                                os_tenant_name,
                                tenant_id=os_tenant_id,
                                user_id=os_user_id,
                                auth_url=os_auth_url,
                                insecure=insecure,
                                region_name=os_region_name,
                                endpoint_type=endpoint_type,
                                extensions=self.extensions,
                                service_type=service_type,
                                service_name=service_name,
                                auth_system=os_auth_system,
                                auth_plugin=auth_plugin,
                                auth_token=auth_token,
                                volume_service_name=volume_service_name,
                                timings=args.timings,
                                bypass_url=bypass_url,
                                os_cache=os_cache,
                                http_log_debug=options.debug,
                                cacert=cacert,
                                timeout=timeout,
                                session=keystone_session,
                                auth=keystone_auth)

        # Now check for the password/token of which pieces of the
        # identifying keyring key can come from the underlying client
        if must_auth:
            helper = SecretsHelper(args, self.cs.client)
            if (auth_plugin and auth_plugin.opts
                    and "os_password" not in auth_plugin.opts):
                use_pw = False
            else:
                use_pw = True

            tenant_id = helper.tenant_id
            # Allow commandline to override cache
            if not auth_token:
                auth_token = helper.auth_token
            if not management_url:
                management_url = helper.management_url
            if tenant_id and auth_token and management_url:
                self.cs.client.tenant_id = tenant_id
                self.cs.client.auth_token = auth_token
                self.cs.client.management_url = management_url
                self.cs.client.password_func = lambda: helper.password
            elif use_pw:
                # We're missing something, so auth with user/pass and save
                # the result in our helper.
                self.cs.client.password = helper.password
                self.cs.client.keyring_saver = helper

        try:
            # This does a couple of bits which are useful even if we've
            # got the token + service URL already. It exits fast in that case.
            if not cliutils.isunauthenticated(args.func):
                if not use_session:
                    # Only call authenticate() if Patron auth plugin is used.
                    # If keystone is used, authentication is handled as part
                    # of session.
                    self.cs.authenticate()
        except exc.Unauthorized:
            raise exc.CommandError(_("Invalid OpenStack Patron credentials."))
        except exc.AuthorizationFailure:
            raise exc.CommandError(_("Unable to authorize user"))

        if options.os_compute_api_version == "3" and service_type != 'image':
            # NOTE(cyeoh): create an image based client because the
            # images api is no longer proxied by the V3 API and we
            # sometimes need to be able to look up images information
            # via glance when connected to the patron api.
            image_service_type = 'image'
            # NOTE(hdd): the password is needed again because creating a new
            # Client without specifying bypass_url will force authentication.
            # We can't reuse self.cs's bypass_url, because that's the URL for
            # the patron service; we need to get glance's URL for this Client
            if not os_password:
                os_password = helper.password
            self.cs.image_cs = client.Client(
                options.os_compute_api_version,
                os_username,
                os_password,
                os_tenant_name,
                tenant_id=os_tenant_id,
                auth_url=os_auth_url,
                insecure=insecure,
                region_name=os_region_name,
                endpoint_type=endpoint_type,
                extensions=self.extensions,
                service_type=image_service_type,
                service_name=service_name,
                auth_system=os_auth_system,
                auth_plugin=auth_plugin,
                volume_service_name=volume_service_name,
                timings=args.timings,
                bypass_url=bypass_url,
                os_cache=os_cache,
                http_log_debug=options.debug,
                session=keystone_session,
                auth=keystone_auth,
                cacert=cacert,
                timeout=timeout)

        args.func(self.cs, args)

        if args.timings:
            self._dump_timings(self.times + self.cs.get_timings())
Example #39
0
    def get_base_parser(self):
        parser = patronclientArgumentParser(
            prog='patron',
            description=__doc__.strip(),
            epilog='See "patron help COMMAND" '
                   'for help on a specific command.',
            add_help=False,
            formatter_class=OpenStackHelpFormatter,
        )

        # Global arguments
        parser.add_argument(
            '-h', '--help',
            action='store_true',
            help=argparse.SUPPRESS,
        )

        parser.add_argument('--version',
                            action='version',
                            version=patronclient.__version__)

        parser.add_argument(
            '--debug',
            default=False,
            action='store_true',
            help=_("Print debugging output"))

        parser.add_argument(
            '--os-cache',
            default=strutils.bool_from_string(
                cliutils.env('OS_CACHE', default=False), True),
            action='store_true',
            help=_("Use the auth token cache. Defaults to False if "
                   "env[OS_CACHE] is not set."))

        parser.add_argument(
            '--timings',
            default=False,
            action='store_true',
            help=_("Print call timing info"))

        parser.add_argument(
            '--os-auth-token',
            default=cliutils.env('OS_AUTH_TOKEN'),
            help='Defaults to env[OS_AUTH_TOKEN]')

        parser.add_argument(
            '--os_username',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--os_password',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--os-tenant-name',
            metavar='<auth-tenant-name>',
            default=cliutils.env('OS_TENANT_NAME', 'PATRON_PROJECT_ID'),
            help=_('Defaults to env[OS_TENANT_NAME].'))
        parser.add_argument(
            '--os_tenant_name',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--os-tenant-id',
            metavar='<auth-tenant-id>',
            default=cliutils.env('OS_TENANT_ID'),
            help=_('Defaults to env[OS_TENANT_ID].'))

        parser.add_argument(
            '--os_auth_url',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--os-region-name',
            metavar='<region-name>',
            default=cliutils.env('OS_REGION_NAME', 'PATRON_REGION_NAME'),
            help=_('Defaults to env[OS_REGION_NAME].'))
        parser.add_argument(
            '--os_region_name',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--os-auth-system',
            metavar='<auth-system>',
            default=cliutils.env('OS_AUTH_SYSTEM'),
            help='Defaults to env[OS_AUTH_SYSTEM].')
        parser.add_argument(
            '--os_auth_system',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--service-type',
            metavar='<service-type>',
            help=_('Defaults to compute for most actions'))
        parser.add_argument(
            '--service_type',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--service-name',
            metavar='<service-name>',
            default=cliutils.env('PATRON_SERVICE_NAME'),
            help=_('Defaults to env[PATRON_SERVICE_NAME]'))
        parser.add_argument(
            '--service_name',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--volume-service-name',
            metavar='<volume-service-name>',
            default=cliutils.env('PATRON_VOLUME_SERVICE_NAME'),
            help=_('Defaults to env[PATRON_VOLUME_SERVICE_NAME]'))
        parser.add_argument(
            '--volume_service_name',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--os-endpoint-type',
            metavar='<endpoint-type>',
            dest='endpoint_type',
            default=cliutils.env(
                'PATRON_ENDPOINT_TYPE',
                default=cliutils.env(
                    'OS_ENDPOINT_TYPE',
                    default=DEFAULT_PATRON_ENDPOINT_TYPE)),
            help=_('Defaults to env[PATRON_ENDPOINT_TYPE], '
                   'env[OS_ENDPOINT_TYPE] or ') +
                 DEFAULT_PATRON_ENDPOINT_TYPE + '.')

        parser.add_argument(
            '--endpoint-type',
            help=argparse.SUPPRESS)
        # NOTE(dtroyer): We can't add --endpoint_type here due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.  I'm leaving this here for doc purposes.
        # parser.add_argument('--endpoint_type',
        #     help=argparse.SUPPRESS)

        parser.add_argument(
            '--os-compute-api-version',
            metavar='<compute-api-ver>',
            default=cliutils.env('OS_COMPUTE_API_VERSION',
                                 default=DEFAULT_OS_COMPUTE_API_VERSION),
            help=_('Accepts 1.1 or 3, '
                   'defaults to env[OS_COMPUTE_API_VERSION].'))
        parser.add_argument(
            '--os_compute_api_version',
            help=argparse.SUPPRESS)

        parser.add_argument(
            '--bypass-url',
            metavar='<bypass-url>',
            dest='bypass_url',
            default=cliutils.env('patronclient_BYPASS_URL'),
            help="Use this API endpoint instead of the Service Catalog. "
                 "Defaults to env[patronclient_BYPASS_URL]")
        parser.add_argument('--bypass_url',
                            help=argparse.SUPPRESS)

        # The auth-system-plugins might require some extra options
        patronclient.auth_plugin.load_auth_system_opts(parser)

        self._append_global_identity_args(parser)

        return parser
Example #40
0
    def main(self, argv):
        # Parse args once to find version and debug settings
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(argv)
        self.setup_debugging(options.debug)

        # Discover available auth plugins
        patronclient.auth_plugin.discover_auth_systems()

        # build available subcommands based on version
        self.extensions = self._discover_extensions(
            options.os_compute_api_version)
        self._run_extension_hooks('__pre_parse_args__')

        # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.
        if '--endpoint_type' in argv:
            spot = argv.index('--endpoint_type')
            argv[spot] = '--endpoint-type'

        subcommand_parser = self.get_subcommand_parser(
            options.os_compute_api_version)
        self.parser = subcommand_parser

        if options.help or not argv:
            subcommand_parser.print_help()
            return 0

        args = subcommand_parser.parse_args(argv)
        self._run_extension_hooks('__post_parse_args__', args)

        # Short-circuit and deal with help right away.
        if args.func == self.do_help:
            self.do_help(args)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        os_username = args.os_username
        os_user_id = args.os_user_id
        os_password = None  # Fetched and set later as needed
        os_tenant_name = args.os_tenant_name
        os_tenant_id = args.os_tenant_id
        os_auth_url = args.os_auth_url
        os_region_name = args.os_region_name
        os_auth_system = args.os_auth_system
        endpoint_type = args.endpoint_type
        insecure = args.insecure
        service_type = args.service_type
        service_name = args.service_name
        volume_service_name = args.volume_service_name
        bypass_url = args.bypass_url
        os_cache = args.os_cache
        cacert = args.os_cacert
        timeout = args.timeout

        keystone_session = None
        keystone_auth = None

        # We may have either, both or none of these.
        # If we have both, we don't need USERNAME, PASSWORD etc.
        # Fill in the blanks from the SecretsHelper if possible.
        # Finally, authenticate unless we have both.
        # Note if we don't auth we probably don't have a tenant ID so we can't
        # cache the token.
        auth_token = args.os_auth_token if args.os_auth_token else None
        management_url = bypass_url if bypass_url else None

        if os_auth_system and os_auth_system != "keystone":
            auth_plugin = patronclient.auth_plugin.load_plugin(os_auth_system)
        else:
            auth_plugin = None

        if not endpoint_type:
            endpoint_type = DEFAULT_PATRON_ENDPOINT_TYPE

        # This allow users to use endpoint_type as (internal, public or admin)
        # just like other openstack clients (glance, cinder etc)
        if endpoint_type in ['internal', 'public', 'admin']:
            endpoint_type += 'URL'

        if not service_type:
            os_compute_api_version = (options.os_compute_api_version or
                                      DEFAULT_OS_COMPUTE_API_VERSION)
            try:
                service_type = DEFAULT_PATRON_SERVICE_TYPE_MAP[
                    os_compute_api_version]
            except KeyError:
                service_type = DEFAULT_PATRON_SERVICE_TYPE_MAP[
                    DEFAULT_OS_COMPUTE_API_VERSION]
            service_type = cliutils.get_service_type(args.func) or service_type

        # If we have an auth token but no management_url, we must auth anyway.
        # Expired tokens are handled by client.py:_cs_request
        must_auth = not (cliutils.isunauthenticated(args.func)
                         or (auth_token and management_url))

        # Do not use Keystone session for cases with no session support. The
        # presence of auth_plugin means os_auth_system is present and is not
        # keystone.
        use_session = True
        if auth_plugin or bypass_url or os_cache or volume_service_name:
            use_session = False

        # FIXME(usrleon): Here should be restrict for project id same as
        # for os_username or os_password but for compatibility it is not.
        if must_auth:
            if auth_plugin:
                auth_plugin.parse_opts(args)

            if not auth_plugin or not auth_plugin.opts:
                if not os_username and not os_user_id:
                    raise exc.CommandError(
                        _("You must provide a username "
                          "or user id via --os-username, --os-user-id, "
                          "env[OS_USERNAME] or env[OS_USER_ID]"))

            if not any([args.os_tenant_name, args.os_tenant_id,
                        args.os_project_id, args.os_project_name]):
                raise exc.CommandError(_("You must provide a project name or"
                                         " project id via --os-project-name,"
                                         " --os-project-id, env[OS_PROJECT_ID]"
                                         " or env[OS_PROJECT_NAME]. You may"
                                         " use os-project and os-tenant"
                                         " interchangeably."))

            if not os_auth_url:
                if os_auth_system and os_auth_system != 'keystone':
                    os_auth_url = auth_plugin.get_auth_url()

            if not os_auth_url:
                    raise exc.CommandError(
                        _("You must provide an auth url "
                          "via either --os-auth-url or env[OS_AUTH_URL] "
                          "or specify an auth_system which defines a "
                          "default url with --os-auth-system "
                          "or env[OS_AUTH_SYSTEM]"))

            project_id = args.os_project_id or args.os_tenant_id
            project_name = args.os_project_name or args.os_tenant_name
            if use_session:
                # Not using Patron auth plugin, so use keystone
                start_time = time.time()
                keystone_session = ksession.Session.load_from_cli_options(args)
                keystone_auth = self._get_keystone_auth(
                    keystone_session,
                    args.os_auth_url,
                    username=args.os_username,
                    user_id=args.os_user_id,
                    user_domain_id=args.os_user_domain_id,
                    user_domain_name=args.os_user_domain_name,
                    password=args.os_password,
                    auth_token=args.os_auth_token,
                    project_id=project_id,
                    project_name=project_name,
                    project_domain_id=args.os_project_domain_id,
                    project_domain_name=args.os_project_domain_name)
                end_time = time.time()
                self.times.append(
                    ('%s %s' % ('auth_url', args.os_auth_url),
                     start_time, end_time))

        if (options.os_compute_api_version and
                options.os_compute_api_version != '1.0'):
            if not any([args.os_tenant_id, args.os_tenant_name,
                        args.os_project_id, args.os_project_name]):
                raise exc.CommandError(_("You must provide a project name or"
                                         " project id via --os-project-name,"
                                         " --os-project-id, env[OS_PROJECT_ID]"
                                         " or env[OS_PROJECT_NAME]. You may"
                                         " use os-project and os-tenant"
                                         " interchangeably."))

            if not os_auth_url:
                raise exc.CommandError(
                    _("You must provide an auth url "
                      "via either --os-auth-url or env[OS_AUTH_URL]"))

        self.cs = client.Client(
            options.os_compute_api_version,
            os_username, os_password, os_tenant_name,
            tenant_id=os_tenant_id, user_id=os_user_id,
            auth_url=os_auth_url, insecure=insecure,
            region_name=os_region_name, endpoint_type=endpoint_type,
            extensions=self.extensions, service_type=service_type,
            service_name=service_name, auth_system=os_auth_system,
            auth_plugin=auth_plugin, auth_token=auth_token,
            volume_service_name=volume_service_name,
            timings=args.timings, bypass_url=bypass_url,
            os_cache=os_cache, http_log_debug=options.debug,
            cacert=cacert, timeout=timeout,
            session=keystone_session, auth=keystone_auth)

        # Now check for the password/token of which pieces of the
        # identifying keyring key can come from the underlying client
        if must_auth:
            helper = SecretsHelper(args, self.cs.client)
            if (auth_plugin and auth_plugin.opts and
                    "os_password" not in auth_plugin.opts):
                use_pw = False
            else:
                use_pw = True

            tenant_id = helper.tenant_id
            # Allow commandline to override cache
            if not auth_token:
                auth_token = helper.auth_token
            if not management_url:
                management_url = helper.management_url
            if tenant_id and auth_token and management_url:
                self.cs.client.tenant_id = tenant_id
                self.cs.client.auth_token = auth_token
                self.cs.client.management_url = management_url
                self.cs.client.password_func = lambda: helper.password
            elif use_pw:
                # We're missing something, so auth with user/pass and save
                # the result in our helper.
                self.cs.client.password = helper.password
                self.cs.client.keyring_saver = helper

        try:
            # This does a couple of bits which are useful even if we've
            # got the token + service URL already. It exits fast in that case.
            if not cliutils.isunauthenticated(args.func):
                if not use_session:
                    # Only call authenticate() if Patron auth plugin is used.
                    # If keystone is used, authentication is handled as part
                    # of session.
                    self.cs.authenticate()
        except exc.Unauthorized:
            raise exc.CommandError(_("Invalid OpenStack Patron credentials."))
        except exc.AuthorizationFailure:
            raise exc.CommandError(_("Unable to authorize user"))

        if options.os_compute_api_version == "3" and service_type != 'image':
            # NOTE(cyeoh): create an image based client because the
            # images api is no longer proxied by the V3 API and we
            # sometimes need to be able to look up images information
            # via glance when connected to the patron api.
            image_service_type = 'image'
            # NOTE(hdd): the password is needed again because creating a new
            # Client without specifying bypass_url will force authentication.
            # We can't reuse self.cs's bypass_url, because that's the URL for
            # the patron service; we need to get glance's URL for this Client
            if not os_password:
                os_password = helper.password
            self.cs.image_cs = client.Client(
                options.os_compute_api_version, os_username,
                os_password, os_tenant_name, tenant_id=os_tenant_id,
                auth_url=os_auth_url, insecure=insecure,
                region_name=os_region_name, endpoint_type=endpoint_type,
                extensions=self.extensions, service_type=image_service_type,
                service_name=service_name, auth_system=os_auth_system,
                auth_plugin=auth_plugin,
                volume_service_name=volume_service_name,
                timings=args.timings, bypass_url=bypass_url,
                os_cache=os_cache, http_log_debug=options.debug,
                session=keystone_session, auth=keystone_auth,
                cacert=cacert, timeout=timeout)

        args.func(self.cs, args)

        if args.timings:
            self._dump_timings(self.times + self.cs.get_timings())
Example #41
0
        :param node_id: The ID of the node to list.
        :rtype: list
        """
        interfaces = []
        node = self._get("/os-baremetal-nodes/%s" % node_id, 'node')
        for interface in node.interfaces:
            interface_object = BareMetalNodeInterface(self, interface)
            interfaces.append(interface_object)
        return interfaces


@cliutils.arg(
    'service_host',
    metavar='<service_host>',
    help=_('Name of patron compute host which will control this baremetal '
           'node'))
@cliutils.arg(
    'cpus',
    metavar='<cpus>',
    type=int,
    help=_('Number of CPUs in the node'))
@cliutils.arg(
    'memory_mb',
    metavar='<memory_mb>',
    type=int,
    help=_('Megabytes of RAM in the node'))
@cliutils.arg(
    'local_gb',
    metavar='<local_gb>',
    type=int,
    help=_('Gigabytes of local storage in the node'))
Example #42
0
        success = False
        error_message = _("Error while evacuating instance: %s") % e
    return EvacuateHostResponse(
        base.Manager, {
            "server_uuid": server['uuid'],
            "evacuate_accepted": success,
            "error_message": error_message
        })


@cliutils.arg('host', metavar='<host>', help='Name of host.')
@cliutils.arg(
    '--target_host',
    metavar='<target_host>',
    default=None,
    help=_('Name of target host. If no host is specified the scheduler will '
           'select a target.'))
@cliutils.arg(
    '--on-shared-storage',
    dest='on_shared_storage',
    action="store_true",
    default=False,
    help=_('Specifies whether all instances files are on shared storage'))
def do_host_evacuate(cs, args):
    """Evacuate all instances from failed host."""
    hypervisors = cs.hypervisors.search(args.host, servers=True)
    response = []
    for hyper in hypervisors:
        if hasattr(hyper, 'servers'):
            for server in hyper.servers:
                response.append(_server_evacuate(cs, server, args))
Example #43
0
    def get_base_parser(self):
        parser = patronclientArgumentParser(
            prog='patron',
            description=__doc__.strip(),
            epilog='See "patron help COMMAND" '
            'for help on a specific command.',
            add_help=False,
            formatter_class=OpenStackHelpFormatter,
        )

        # Global arguments
        parser.add_argument(
            '-h',
            '--help',
            action='store_true',
            help=argparse.SUPPRESS,
        )

        parser.add_argument('--version',
                            action='version',
                            version=patronclient.__version__)

        parser.add_argument('--debug',
                            default=False,
                            action='store_true',
                            help=_("Print debugging output"))

        parser.add_argument(
            '--os-cache',
            default=strutils.bool_from_string(
                cliutils.env('OS_CACHE', default=False), True),
            action='store_true',
            help=_("Use the auth token cache. Defaults to False if "
                   "env[OS_CACHE] is not set."))

        parser.add_argument('--timings',
                            default=False,
                            action='store_true',
                            help=_("Print call timing info"))

        parser.add_argument('--os-auth-token',
                            default=cliutils.env('OS_AUTH_TOKEN'),
                            help='Defaults to env[OS_AUTH_TOKEN]')

        parser.add_argument('--os_username', help=argparse.SUPPRESS)

        parser.add_argument('--os_password', help=argparse.SUPPRESS)

        parser.add_argument('--os-tenant-name',
                            metavar='<auth-tenant-name>',
                            default=cliutils.env('OS_TENANT_NAME',
                                                 'PATRON_PROJECT_ID'),
                            help=_('Defaults to env[OS_TENANT_NAME].'))
        parser.add_argument('--os_tenant_name', help=argparse.SUPPRESS)

        parser.add_argument('--os-tenant-id',
                            metavar='<auth-tenant-id>',
                            default=cliutils.env('OS_TENANT_ID'),
                            help=_('Defaults to env[OS_TENANT_ID].'))

        parser.add_argument('--os_auth_url', help=argparse.SUPPRESS)

        parser.add_argument('--os-region-name',
                            metavar='<region-name>',
                            default=cliutils.env('OS_REGION_NAME',
                                                 'PATRON_REGION_NAME'),
                            help=_('Defaults to env[OS_REGION_NAME].'))
        parser.add_argument('--os_region_name', help=argparse.SUPPRESS)

        parser.add_argument('--os-auth-system',
                            metavar='<auth-system>',
                            default=cliutils.env('OS_AUTH_SYSTEM'),
                            help='Defaults to env[OS_AUTH_SYSTEM].')
        parser.add_argument('--os_auth_system', help=argparse.SUPPRESS)

        parser.add_argument('--service-type',
                            metavar='<service-type>',
                            help=_('Defaults to compute for most actions'))
        parser.add_argument('--service_type', help=argparse.SUPPRESS)

        parser.add_argument('--service-name',
                            metavar='<service-name>',
                            default=cliutils.env('PATRON_SERVICE_NAME'),
                            help=_('Defaults to env[PATRON_SERVICE_NAME]'))
        parser.add_argument('--service_name', help=argparse.SUPPRESS)

        parser.add_argument(
            '--volume-service-name',
            metavar='<volume-service-name>',
            default=cliutils.env('PATRON_VOLUME_SERVICE_NAME'),
            help=_('Defaults to env[PATRON_VOLUME_SERVICE_NAME]'))
        parser.add_argument('--volume_service_name', help=argparse.SUPPRESS)

        parser.add_argument('--os-endpoint-type',
                            metavar='<endpoint-type>',
                            dest='endpoint_type',
                            default=cliutils.env(
                                'PATRON_ENDPOINT_TYPE',
                                default=cliutils.env(
                                    'OS_ENDPOINT_TYPE',
                                    default=DEFAULT_PATRON_ENDPOINT_TYPE)),
                            help=_('Defaults to env[PATRON_ENDPOINT_TYPE], '
                                   'env[OS_ENDPOINT_TYPE] or ') +
                            DEFAULT_PATRON_ENDPOINT_TYPE + '.')

        parser.add_argument('--endpoint-type', help=argparse.SUPPRESS)
        # NOTE(dtroyer): We can't add --endpoint_type here due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.  I'm leaving this here for doc purposes.
        # parser.add_argument('--endpoint_type',
        #     help=argparse.SUPPRESS)

        parser.add_argument('--os-compute-api-version',
                            metavar='<compute-api-ver>',
                            default=cliutils.env(
                                'OS_COMPUTE_API_VERSION',
                                default=DEFAULT_OS_COMPUTE_API_VERSION),
                            help=_('Accepts 1.1 or 3, '
                                   'defaults to env[OS_COMPUTE_API_VERSION].'))
        parser.add_argument('--os_compute_api_version', help=argparse.SUPPRESS)

        parser.add_argument(
            '--bypass-url',
            metavar='<bypass-url>',
            dest='bypass_url',
            default=cliutils.env('patronclient_BYPASS_URL'),
            help="Use this API endpoint instead of the Service Catalog. "
            "Defaults to env[patronclient_BYPASS_URL]")
        parser.add_argument('--bypass_url', help=argparse.SUPPRESS)

        # The auth-system-plugins might require some extra options
        patronclient.auth_plugin.load_auth_system_opts(parser)

        self._append_global_identity_args(parser)

        return parser
Example #44
0
    success = True
    error_message = ""
    try:
        cs.servers.live_migrate(server['uuid'], args.target_host,
                                args.block_migrate, args.disk_over_commit)
    except Exception as e:
        success = False
        error_message = _("Error while live migrating instance: %s") % e
    return HostEvacuateLiveResponse(server['uuid'], success, error_message)


@cliutils.arg('host', metavar='<host>', help='Name of host.')
@cliutils.arg('--target-host',
              metavar='<target_host>',
              default=None,
              help=_('Name of target host.'))
@cliutils.arg('--block-migrate',
              action='store_true',
              default=False,
              help=_('Enable block migration.'))
@cliutils.arg('--disk-over-commit',
              action='store_true',
              default=False,
              help=_('Enable disk overcommit.'))
def do_host_evacuate_live(cs, args):
    """Live migrate all instances of the specified host
    to other available hosts.
    """
    hypervisors = cs.hypervisors.search(args.host, servers=True)
    response = []
    for hyper in hypervisors:
Example #45
0
    """
    do_tenant_network_list(cs, args)


def do_tenant_network_list(cs, args):
    """
    List tenant networks.
    """
    networks = cs.tenant_networks.list()
    utils.print_list(networks, ['ID', 'Label', 'CIDR'])


@cliutils.arg(
    'label',
    metavar='<network_label>',
    help=_('Network label (ex. my_new_network)'))
@cliutils.arg(
    'cidr',
    metavar='<cidr>',
    help=_('IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)'))
def do_net_create(cs, args):
    """
    DEPRECATED, use tenant-network-create instead.
    """
    do_tenant_network_create(cs, args)


@cliutils.arg(
    'label',
    metavar='<network_label>',
    help=_('Network label (ex. my_new_network)'))
Example #46
0
                            on_shared_storage=args.on_shared_storage)
    except Exception as e:
        success = False
        error_message = _("Error while evacuating instance: %s") % e
    return EvacuateHostResponse(base.Manager,
                                {"server_uuid": server['uuid'],
                                 "evacuate_accepted": success,
                                 "error_message": error_message})


@cliutils.arg('host', metavar='<host>', help='Name of host.')
@cliutils.arg(
    '--target_host',
    metavar='<target_host>',
    default=None,
    help=_('Name of target host. If no host is specified the scheduler will '
           'select a target.'))
@cliutils.arg(
    '--on-shared-storage',
    dest='on_shared_storage',
    action="store_true",
    default=False,
    help=_('Specifies whether all instances files are on shared storage'))
def do_host_evacuate(cs, args):
    """Evacuate all instances from failed host."""
    hypervisors = cs.hypervisors.search(args.host, servers=True)
    response = []
    for hyper in hypervisors:
        if hasattr(hyper, 'servers'):
            for server in hyper.servers:
                response.append(_server_evacuate(cs, server, args))