Alessandro Pilotti 10 лет назад
Родитель
Сommit
eb6e259a96

+ 68 - 68
coriolis/api/middleware/auth.py

@@ -1,68 +1,68 @@
-import webob
-
-from oslo_log import log as logging
-from oslo_middleware import request_id
-from oslo_serialization import jsonutils
-
-from coriolis.api import wsgi
-from coriolis import context
-from coriolis.i18n import _
-
-LOG = logging.getLogger(__name__)
-
-
-class CoriolisKeystoneContext(wsgi.Middleware):
-    @webob.dec.wsgify(RequestClass=wsgi.Request)
-    def __call__(self, req):
-        user = req.headers.get('X_USER')
-        user = req.headers.get('X_USER_ID', user)
-        if user is None:
-            LOG.debug("Neither X_USER_ID nor X_USER found in request")
-            return webob.exc.HTTPUnauthorized()
-
-        # get the roles
-        roles = [r.strip() for r in req.headers.get('X_ROLE', '').split(',')]
-        if 'X_TENANT_ID' in req.headers:
-            # This is the new header since Keystone went to ID/Name
-            tenant = req.headers['X_TENANT_ID']
-        else:
-            # This is for legacy compatibility
-            tenant = req.headers['X_TENANT']
-
-        project_name = req.headers.get('X_TENANT_NAME')
-        project_domain_name = req.headers.get('X-Project-Domain-Name')
-        user_domain_name = req.headers.get('X-User-Domain-Name')
-
-        req_id = req.environ.get(request_id.ENV_REQUEST_ID)
-        # TODO(alexpilotti): Check why it's not str
-        if isinstance(req_id, bytes):
-            req_id = req_id.decode()
-
-        # Get the auth token
-        auth_token = req.headers.get('X_AUTH_TOKEN')
-
-        # Build a context, including the auth_token...
-        remote_address = req.remote_addr
-
-        service_catalog = None
-        if req.headers.get('X_SERVICE_CATALOG') is not None:
-            try:
-                catalog_header = req.headers.get('X_SERVICE_CATALOG')
-                service_catalog = jsonutils.loads(catalog_header)
-            except ValueError:
-                raise webob.exc.HTTPInternalServerError(
-                    explanation=_('Invalid service catalog json.'))
-
-        ctx = context.RequestContext(user,
-                                     tenant,
-                                     project_name=project_name,
-                                     project_domain=project_domain_name,
-                                     user_domain=user_domain_name,
-                                     roles=roles,
-                                     auth_token=auth_token,
-                                     remote_address=remote_address,
-                                     service_catalog=service_catalog,
-                                     request_id=req_id)
-
-        req.environ['coriolis.context'] = ctx
-        return self.application
+import webob
+
+from oslo_log import log as logging
+from oslo_middleware import request_id
+from oslo_serialization import jsonutils
+
+from coriolis.api import wsgi
+from coriolis import context
+from coriolis.i18n import _
+
+LOG = logging.getLogger(__name__)
+
+
+class CoriolisKeystoneContext(wsgi.Middleware):
+    @webob.dec.wsgify(RequestClass=wsgi.Request)
+    def __call__(self, req):
+        user = req.headers.get('X_USER')
+        user = req.headers.get('X_USER_ID', user)
+        if user is None:
+            LOG.debug("Neither X_USER_ID nor X_USER found in request")
+            return webob.exc.HTTPUnauthorized()
+
+        # get the roles
+        roles = [r.strip() for r in req.headers.get('X_ROLE', '').split(',')]
+        if 'X_TENANT_ID' in req.headers:
+            # This is the new header since Keystone went to ID/Name
+            tenant = req.headers['X_TENANT_ID']
+        else:
+            # This is for legacy compatibility
+            tenant = req.headers['X_TENANT']
+
+        project_name = req.headers.get('X_TENANT_NAME')
+        project_domain_name = req.headers.get('X-Project-Domain-Name')
+        user_domain_name = req.headers.get('X-User-Domain-Name')
+
+        req_id = req.environ.get(request_id.ENV_REQUEST_ID)
+        # TODO(alexpilotti): Check why it's not str
+        if isinstance(req_id, bytes):
+            req_id = req_id.decode()
+
+        # Get the auth token
+        auth_token = req.headers.get('X_AUTH_TOKEN')
+
+        # Build a context, including the auth_token...
+        remote_address = req.remote_addr
+
+        service_catalog = None
+        if req.headers.get('X_SERVICE_CATALOG') is not None:
+            try:
+                catalog_header = req.headers.get('X_SERVICE_CATALOG')
+                service_catalog = jsonutils.loads(catalog_header)
+            except ValueError:
+                raise webob.exc.HTTPInternalServerError(
+                    explanation=_('Invalid service catalog json.'))
+
+        ctx = context.RequestContext(user,
+                                     tenant,
+                                     project_name=project_name,
+                                     project_domain=project_domain_name,
+                                     user_domain=user_domain_name,
+                                     roles=roles,
+                                     auth_token=auth_token,
+                                     remote_address=remote_address,
+                                     service_catalog=service_catalog,
+                                     request_id=req_id)
+
+        req.environ['coriolis.context'] = ctx
+        return self.application

+ 5 - 5
coriolis/api/v1/__init__.py

@@ -1,5 +1,5 @@
-import paste.urlmap
-
-
-def root_app_factory(loader, global_conf, **local_conf):
-    return paste.urlmap.urlmap_factory(loader, global_conf, **local_conf)
+import paste.urlmap
+
+
+def root_app_factory(loader, global_conf, **local_conf):
+    return paste.urlmap.urlmap_factory(loader, global_conf, **local_conf)

+ 25 - 25
coriolis/api/v1/migration_actions.py

@@ -1,25 +1,25 @@
-from webob import exc
-
-from coriolis.api import wsgi as api_wsgi
-from coriolis import exception
-from coriolis.migrations import api
-
-
-class MigrationActionsController(api_wsgi.Controller):
-    def __init__(self):
-        self._migration_api = api.API()
-        super(MigrationActionsController, self).__init__()
-
-    @api_wsgi.action('cancel')
-    def _cancel(self, req, id, body):
-        try:
-            self._migration_api.cancel(req.environ['coriolis.context'], id)
-            raise exc.HTTPNoContent()
-        except exception.NotFound as ex:
-            raise exc.HTTPNotFound(explanation=ex.msg)
-        except exception.InvalidParameterValue as ex:
-            raise exc.HTTPNotFound(explanation=ex.msg)
-
-
-def create_resource():
-    return api_wsgi.Resource(MigrationActionsController())
+from webob import exc
+
+from coriolis.api import wsgi as api_wsgi
+from coriolis import exception
+from coriolis.migrations import api
+
+
+class MigrationActionsController(api_wsgi.Controller):
+    def __init__(self):
+        self._migration_api = api.API()
+        super(MigrationActionsController, self).__init__()
+
+    @api_wsgi.action('cancel')
+    def _cancel(self, req, id, body):
+        try:
+            self._migration_api.cancel(req.environ['coriolis.context'], id)
+            raise exc.HTTPNoContent()
+        except exception.NotFound as ex:
+            raise exc.HTTPNotFound(explanation=ex.msg)
+        except exception.InvalidParameterValue as ex:
+            raise exc.HTTPNotFound(explanation=ex.msg)
+
+
+def create_resource():
+    return api_wsgi.Resource(MigrationActionsController())

+ 5 - 5
coriolis/api/v1/views/__init__.py

@@ -1,5 +1,5 @@
-import paste.urlmap
-
-
-def root_app_factory(loader, global_conf, **local_conf):
-    return paste.urlmap.urlmap_factory(loader, global_conf, **local_conf)
+import paste.urlmap
+
+
+def root_app_factory(loader, global_conf, **local_conf):
+    return paste.urlmap.urlmap_factory(loader, global_conf, **local_conf)

+ 21 - 21
coriolis/api/v1/views/migration_view.py

@@ -1,21 +1,21 @@
-import itertools
-
-
-def _format_migration(req, migration, keys=None):
-    def transform(key, value):
-        if keys and key not in keys:
-            return
-        yield (key, value)
-
-    return dict(itertools.chain.from_iterable(
-        transform(k, v) for k, v in migration.items()))
-
-
-def single(req, migration):
-    return {"migration": _format_migration(req, migration)}
-
-
-def collection(req, migrations):
-    formatted_migrations = [_format_migration(req, m)
-                            for m in migrations]
-    return {'migrations': formatted_migrations}
+import itertools
+
+
+def _format_migration(req, migration, keys=None):
+    def transform(key, value):
+        if keys and key not in keys:
+            return
+        yield (key, value)
+
+    return dict(itertools.chain.from_iterable(
+        transform(k, v) for k, v in migration.items()))
+
+
+def single(req, migration):
+    return {"migration": _format_migration(req, migration)}
+
+
+def collection(req, migrations):
+    formatted_migrations = [_format_migration(req, m)
+                            for m in migrations]
+    return {'migrations': formatted_migrations}

+ 20 - 20
coriolis/cmd/db_sync.py

@@ -1,20 +1,20 @@
-import sys
-
-from oslo_config import cfg
-
-from coriolis.db import api as db_api
-from coriolis import utils
-
-CONF = cfg.CONF
-
-
-def main():
-    CONF(sys.argv[1:], project='coriolis',
-         version="1.0.0")
-    utils.setup_logging()
-
-    db_api.db_sync(db_api.get_engine())
-
-
-if __name__ == "__main__":
-    main()
+import sys
+
+from oslo_config import cfg
+
+from coriolis.db import api as db_api
+from coriolis import utils
+
+CONF = cfg.CONF
+
+
+def main():
+    CONF(sys.argv[1:], project='coriolis',
+         version="1.0.0")
+    utils.setup_logging()
+
+    db_api.db_sync(db_api.get_engine())
+
+
+if __name__ == "__main__":
+    main()

+ 48 - 48
coriolis/context.py

@@ -1,48 +1,48 @@
-from oslo_context import context
-from oslo_db.sqlalchemy import enginefacade
-from oslo_utils import timeutils
-
-
-@enginefacade.transaction_context_provider
-class RequestContext(context.RequestContext):
-    def __init__(self, user, tenant, is_admin=None,
-                 roles=None, project_name=None, remote_address=None,
-                 timestamp=None, request_id=None, auth_token=None,
-                 overwrite=True, domain=None, user_domain=None,
-                 project_domain=None, show_deleted=None, **kwargs):
-
-        super(RequestContext, self).__init__(auth_token=auth_token,
-                                             user=user,
-                                             tenant=tenant,
-                                             domain=domain,
-                                             user_domain=user_domain,
-                                             project_domain=project_domain,
-                                             is_admin=is_admin,
-                                             show_deleted=show_deleted,
-                                             request_id=request_id,
-                                             overwrite=overwrite)
-        self.roles = roles or []
-        self.project_name = project_name
-        self.remote_address = remote_address
-        if not timestamp:
-            timestamp = timeutils.utcnow()
-        elif isinstance(timestamp, str):
-            timestamp = timeutils.parse_isotime(timestamp)
-        self.timestamp = timestamp
-
-    def to_dict(self):
-        result = super(RequestContext, self).to_dict()
-        result['user'] = self.user
-        result['tenant'] = self.tenant
-        result['project_name'] = self.project_name
-        result['domain'] = self.domain
-        result['roles'] = self.roles
-        result['remote_address'] = self.remote_address
-        result['timestamp'] = self.timestamp.isoformat()
-        result['request_id'] = self.request_id
-        result['show_deleted'] = self.show_deleted
-        return result
-
-    @classmethod
-    def from_dict(cls, values):
-        return cls(**values)
+from oslo_context import context
+from oslo_db.sqlalchemy import enginefacade
+from oslo_utils import timeutils
+
+
+@enginefacade.transaction_context_provider
+class RequestContext(context.RequestContext):
+    def __init__(self, user, tenant, is_admin=None,
+                 roles=None, project_name=None, remote_address=None,
+                 timestamp=None, request_id=None, auth_token=None,
+                 overwrite=True, domain=None, user_domain=None,
+                 project_domain=None, show_deleted=None, **kwargs):
+
+        super(RequestContext, self).__init__(auth_token=auth_token,
+                                             user=user,
+                                             tenant=tenant,
+                                             domain=domain,
+                                             user_domain=user_domain,
+                                             project_domain=project_domain,
+                                             is_admin=is_admin,
+                                             show_deleted=show_deleted,
+                                             request_id=request_id,
+                                             overwrite=overwrite)
+        self.roles = roles or []
+        self.project_name = project_name
+        self.remote_address = remote_address
+        if not timestamp:
+            timestamp = timeutils.utcnow()
+        elif isinstance(timestamp, str):
+            timestamp = timeutils.parse_isotime(timestamp)
+        self.timestamp = timestamp
+
+    def to_dict(self):
+        result = super(RequestContext, self).to_dict()
+        result['user'] = self.user
+        result['tenant'] = self.tenant
+        result['project_name'] = self.project_name
+        result['domain'] = self.domain
+        result['roles'] = self.roles
+        result['remote_address'] = self.remote_address
+        result['timestamp'] = self.timestamp.isoformat()
+        result['request_id'] = self.request_id
+        result['show_deleted'] = self.show_deleted
+        return result
+
+    @classmethod
+    def from_dict(cls, values):
+        return cls(**values)

+ 56 - 56
coriolis/db/sqlalchemy/types.py

@@ -1,56 +1,56 @@
-
-#
-#    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.
-
-from oslo_serialization import jsonutils
-from sqlalchemy.dialects import mysql
-from sqlalchemy import types
-
-
-class LongText(types.TypeDecorator):
-    impl = types.Text
-
-    def load_dialect_impl(self, dialect):
-        if dialect.name == 'mysql':
-            return dialect.type_descriptor(mysql.LONGTEXT())
-        else:
-            return self.impl
-
-
-class Json(LongText):
-
-    def process_bind_param(self, value, dialect):
-        return jsonutils.dumps(value)
-
-    def process_result_value(self, value, dialect):
-        if value is None:
-            return None
-        return jsonutils.loads(value)
-
-
-class List(types.TypeDecorator):
-    impl = types.Text
-
-    def load_dialect_impl(self, dialect):
-        if dialect.name == 'mysql':
-            return dialect.type_descriptor(mysql.LONGTEXT())
-        else:
-            return self.impl
-
-    def process_bind_param(self, value, dialect):
-        return jsonutils.dumps(value)
-
-    def process_result_value(self, value, dialect):
-        if value is None:
-            return None
-        return jsonutils.loads(value)
+
+#
+#    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.
+
+from oslo_serialization import jsonutils
+from sqlalchemy.dialects import mysql
+from sqlalchemy import types
+
+
+class LongText(types.TypeDecorator):
+    impl = types.Text
+
+    def load_dialect_impl(self, dialect):
+        if dialect.name == 'mysql':
+            return dialect.type_descriptor(mysql.LONGTEXT())
+        else:
+            return self.impl
+
+
+class Json(LongText):
+
+    def process_bind_param(self, value, dialect):
+        return jsonutils.dumps(value)
+
+    def process_result_value(self, value, dialect):
+        if value is None:
+            return None
+        return jsonutils.loads(value)
+
+
+class List(types.TypeDecorator):
+    impl = types.Text
+
+    def load_dialect_impl(self, dialect):
+        if dialect.name == 'mysql':
+            return dialect.type_descriptor(mysql.LONGTEXT())
+        else:
+            return self.impl
+
+    def process_bind_param(self, value, dialect):
+        return jsonutils.dumps(value)
+
+    def process_result_value(self, value, dialect):
+        if value is None:
+            return None
+        return jsonutils.loads(value)

+ 51 - 51
coriolis/events.py

@@ -1,51 +1,51 @@
-import abc
-
-
-class EventManager(object):
-    __metaclass__ = abc.ABCMeta
-
-    def __init__(self, event_handler):
-        self._event_handler = event_handler
-        self._current_step = 0
-        self._total_steps = None
-
-    def set_total_progress_steps(self, total_steps):
-        self._total_steps = total_steps
-
-    def progress_update(self, message):
-        self._current_step += 1
-        if self._event_handler:
-            self._event_handler.progress_update(
-                self._current_step, self._total_steps, message)
-
-    def info(self, message):
-        if self._event_handler:
-            self._event_handler.info(message)
-
-    def warn(self, message):
-        if self._event_handler:
-            self._event_handler.warn(message)
-
-    def error(self, message):
-        if self._event_handler:
-            self._event_handler.error(message)
-
-
-class BaseEventHandler(object):
-    __metaclass__ = abc.ABCMeta
-
-    @abc.abstractmethod
-    def progress_update(self, current_step, total_steps, message):
-        pass
-
-    @abc.abstractmethod
-    def info(self, message):
-        pass
-
-    @abc.abstractmethod
-    def warn(self, message):
-        pass
-
-    @abc.abstractmethod
-    def error(self, message):
-        pass
+import abc
+
+
+class EventManager(object):
+    __metaclass__ = abc.ABCMeta
+
+    def __init__(self, event_handler):
+        self._event_handler = event_handler
+        self._current_step = 0
+        self._total_steps = None
+
+    def set_total_progress_steps(self, total_steps):
+        self._total_steps = total_steps
+
+    def progress_update(self, message):
+        self._current_step += 1
+        if self._event_handler:
+            self._event_handler.progress_update(
+                self._current_step, self._total_steps, message)
+
+    def info(self, message):
+        if self._event_handler:
+            self._event_handler.info(message)
+
+    def warn(self, message):
+        if self._event_handler:
+            self._event_handler.warn(message)
+
+    def error(self, message):
+        if self._event_handler:
+            self._event_handler.error(message)
+
+
+class BaseEventHandler(object):
+    __metaclass__ = abc.ABCMeta
+
+    @abc.abstractmethod
+    def progress_update(self, current_step, total_steps, message):
+        pass
+
+    @abc.abstractmethod
+    def info(self, message):
+        pass
+
+    @abc.abstractmethod
+    def warn(self, message):
+        pass
+
+    @abc.abstractmethod
+    def error(self, message):
+        pass

+ 70 - 70
coriolis/keystone.py

@@ -1,70 +1,70 @@
-from keystoneauth1 import loading
-from keystoneauth1 import session
-from oslo_config import cfg
-
-from coriolis import exception
-
-opts = [
-    cfg.StrOpt('auth_url',
-               default=None,
-               help='Default auth URL to be used when not specified in the'
-               ' migration\'s connection info.'),
-    cfg.StrOpt('identity_api_version',
-               default=2,
-               help='Default Keystone API version.'),
-    cfg.BoolOpt('allow_untrusted',
-                default=False,
-                help='Allow untrusted SSL/TLS certificates.'),
-]
-
-CONF = cfg.CONF
-CONF.register_opts(opts, 'keystone')
-
-
-def create_keystone_session(ctxt, connection_info={}):
-    keystone_version = connection_info.get(
-        "identity_api_version", CONF.keystone.identity_api_version)
-    auth_url = connection_info.get("auth_url", CONF.keystone.auth_url)
-
-    if not auth_url:
-        raise exception.CoriolisException(
-            '"auth_url" not provided in "connection_info" and option '
-            '"auth_url" in group "[openstack_migration_provider]" '
-            'not set')
-
-    username = connection_info.get("username")
-    password = connection_info.get("password")
-    project_name = connection_info.get("project_name", ctxt.project_name)
-    project_domain_name = connection_info.get(
-        "project_domain_name", ctxt.project_domain)
-    user_domain_name = connection_info.get(
-        "user_domain_name", ctxt.user_domain)
-    allow_untrusted = connection_info.get(
-        "allow_untrusted", CONF.keystone.allow_untrusted)
-
-    # TODO: add "ca_cert" to connection_info
-    verify = not allow_untrusted
-
-    plugin_args = {
-        "auth_url": auth_url,
-        "project_name": project_name,
-    }
-
-    if username:
-        plugin_name = "password"
-        plugin_args["username"] = username
-        plugin_args["password"] = password
-    else:
-        plugin_name = "token"
-        plugin_args["token"] = ctxt.auth_token
-
-    if keystone_version == 3:
-        plugin_name = "v3" + plugin_name
-        plugin_args["project_domain_name"] = project_domain_name
-        if username:
-            plugin_args["user_domain_name"] = user_domain_name
-
-    loader = loading.get_plugin_loader(plugin_name)
-    auth = loader.load_from_options(**plugin_args)
-
-    return session.Session(auth=auth, verify=verify)
+from keystoneauth1 import loading
+from keystoneauth1 import session
+from oslo_config import cfg
+
+from coriolis import exception
+
+opts = [
+    cfg.StrOpt('auth_url',
+               default=None,
+               help='Default auth URL to be used when not specified in the'
+               ' migration\'s connection info.'),
+    cfg.StrOpt('identity_api_version',
+               default=2,
+               help='Default Keystone API version.'),
+    cfg.BoolOpt('allow_untrusted',
+                default=False,
+                help='Allow untrusted SSL/TLS certificates.'),
+]
+
+CONF = cfg.CONF
+CONF.register_opts(opts, 'keystone')
+
+
+def create_keystone_session(ctxt, connection_info={}):
+    keystone_version = connection_info.get(
+        "identity_api_version", CONF.keystone.identity_api_version)
+    auth_url = connection_info.get("auth_url", CONF.keystone.auth_url)
+
+    if not auth_url:
+        raise exception.CoriolisException(
+            '"auth_url" not provided in "connection_info" and option '
+            '"auth_url" in group "[openstack_migration_provider]" '
+            'not set')
+
+    username = connection_info.get("username")
+    password = connection_info.get("password")
+    project_name = connection_info.get("project_name", ctxt.project_name)
+    project_domain_name = connection_info.get(
+        "project_domain_name", ctxt.project_domain)
+    user_domain_name = connection_info.get(
+        "user_domain_name", ctxt.user_domain)
+    allow_untrusted = connection_info.get(
+        "allow_untrusted", CONF.keystone.allow_untrusted)
+
+    # TODO: add "ca_cert" to connection_info
+    verify = not allow_untrusted
+
+    plugin_args = {
+        "auth_url": auth_url,
+        "project_name": project_name,
+    }
+
+    if username:
+        plugin_name = "password"
+        plugin_args["username"] = username
+        plugin_args["password"] = password
+    else:
+        plugin_name = "token"
+        plugin_args["token"] = ctxt.auth_token
+
+    if keystone_version == 3:
+        plugin_name = "v3" + plugin_name
+        plugin_args["project_domain_name"] = project_domain_name
+        if username:
+            plugin_args["user_domain_name"] = user_domain_name
+
+    loader = loading.get_plugin_loader(plugin_name)
+    auth = loader.load_from_options(**plugin_args)
+
+    return session.Session(auth=auth, verify=verify)

+ 38 - 38
coriolis/osmorphing/factory.py

@@ -1,38 +1,38 @@
-import itertools
-
-from oslo_log import log as logging
-
-from coriolis import constants
-from coriolis import exception
-from coriolis.osmorphing import debian
-from coriolis.osmorphing import redhat
-from coriolis.osmorphing import suse
-from coriolis.osmorphing import ubuntu
-from coriolis.osmorphing import windows
-
-LOG = logging.getLogger(__name__)
-
-
-def get_os_morphing_tools(conn, os_type, os_root_dir, target_hypervisor,
-                          target_platform, event_manager):
-    os_morphing_tools_clss = {
-        constants.OS_TYPE_LINUX: [debian.DebianMorphingTools,
-                                  ubuntu.UbuntuMorphingTools,
-                                  redhat.RedHatMorphingTools,
-                                  suse.SUSEMorphingTools],
-        constants.OS_TYPE_WINDOWS: [windows.WindowsMorphingTools],
-        }
-
-    if os_type and os_type not in os_morphing_tools_clss:
-        raise exception.CoriolisException("Unsupported OS type: %s" % os_type)
-
-    for cls in os_morphing_tools_clss.get(
-            os_type, itertools.chain(*os_morphing_tools_clss.values())):
-        tools = cls(conn, os_root_dir, target_hypervisor, target_platform,
-                    event_manager)
-        LOG.debug("Testing OS morphing tools: %s", cls.__name__)
-        os_info = tools.check_os()
-        if os_info:
-            return (tools, os_info)
-    raise exception.CoriolisException(
-        "Cannot find the morphing tools for this OS image")
+import itertools
+
+from oslo_log import log as logging
+
+from coriolis import constants
+from coriolis import exception
+from coriolis.osmorphing import debian
+from coriolis.osmorphing import redhat
+from coriolis.osmorphing import suse
+from coriolis.osmorphing import ubuntu
+from coriolis.osmorphing import windows
+
+LOG = logging.getLogger(__name__)
+
+
+def get_os_morphing_tools(conn, os_type, os_root_dir, target_hypervisor,
+                          target_platform, event_manager):
+    os_morphing_tools_clss = {
+        constants.OS_TYPE_LINUX: [debian.DebianMorphingTools,
+                                  ubuntu.UbuntuMorphingTools,
+                                  redhat.RedHatMorphingTools,
+                                  suse.SUSEMorphingTools],
+        constants.OS_TYPE_WINDOWS: [windows.WindowsMorphingTools],
+        }
+
+    if os_type and os_type not in os_morphing_tools_clss:
+        raise exception.CoriolisException("Unsupported OS type: %s" % os_type)
+
+    for cls in os_morphing_tools_clss.get(
+            os_type, itertools.chain(*os_morphing_tools_clss.values())):
+        tools = cls(conn, os_root_dir, target_hypervisor, target_platform,
+                    event_manager)
+        LOG.debug("Testing OS morphing tools: %s", cls.__name__)
+        os_info = tools.check_os()
+        if os_info:
+            return (tools, os_info)
+    raise exception.CoriolisException(
+        "Cannot find the morphing tools for this OS image")

+ 45 - 45
coriolis/osmorphing/manager.py

@@ -1,45 +1,45 @@
-from oslo_log import log as logging
-
-from coriolis.osmorphing import factory as osmorphing_factory
-from coriolis.osmorphing.osmount import factory as osmount_factory
-
-LOG = logging.getLogger(__name__)
-
-
-def morph_image(connection_info, os_type, target_hypervisor, target_platform,
-                nics_info, event_manager, ignore_devices=[]):
-    os_mount_tools = osmount_factory.get_os_mount_tools(
-        os_type, connection_info, event_manager, ignore_devices)
-
-    event_manager.progress_update("Discovering and mounting OS partitions")
-    os_root_dir, other_mounted_dirs = os_mount_tools.mount_os()
-
-    conn = os_mount_tools.get_connection()
-    os_morphing_tools, os_info = osmorphing_factory.get_os_morphing_tools(
-        conn, os_type, os_root_dir, target_hypervisor, target_platform,
-        event_manager)
-
-    event_manager.progress_update('OS being migrated: %s' % str(os_info))
-
-    os_morphing_tools.set_net_config(nics_info, dhcp=True)
-    LOG.info("Pre packages")
-    os_morphing_tools.pre_packages_install()
-
-    (packages_add,
-     packages_remove) = os_morphing_tools.get_packages()
-
-    if packages_add:
-        event_manager.progress_update(
-            "Adding packages: %s" % str(packages_add))
-        os_morphing_tools.install_packages(packages_add)
-
-    if packages_remove:
-        event_manager.progress_update(
-            "Removing packages: %s" % str(packages_remove))
-        os_morphing_tools.uninstall_packages(packages_remove)
-
-    LOG.info("Post packages")
-    os_morphing_tools.post_packages_install()
-
-    event_manager.progress_update("Dismounting OS partitions")
-    os_mount_tools.dismount_os(other_mounted_dirs + [os_root_dir])
+from oslo_log import log as logging
+
+from coriolis.osmorphing import factory as osmorphing_factory
+from coriolis.osmorphing.osmount import factory as osmount_factory
+
+LOG = logging.getLogger(__name__)
+
+
+def morph_image(connection_info, os_type, target_hypervisor, target_platform,
+                nics_info, event_manager, ignore_devices=[]):
+    os_mount_tools = osmount_factory.get_os_mount_tools(
+        os_type, connection_info, event_manager, ignore_devices)
+
+    event_manager.progress_update("Discovering and mounting OS partitions")
+    os_root_dir, other_mounted_dirs = os_mount_tools.mount_os()
+
+    conn = os_mount_tools.get_connection()
+    os_morphing_tools, os_info = osmorphing_factory.get_os_morphing_tools(
+        conn, os_type, os_root_dir, target_hypervisor, target_platform,
+        event_manager)
+
+    event_manager.progress_update('OS being migrated: %s' % str(os_info))
+
+    os_morphing_tools.set_net_config(nics_info, dhcp=True)
+    LOG.info("Pre packages")
+    os_morphing_tools.pre_packages_install()
+
+    (packages_add,
+     packages_remove) = os_morphing_tools.get_packages()
+
+    if packages_add:
+        event_manager.progress_update(
+            "Adding packages: %s" % str(packages_add))
+        os_morphing_tools.install_packages(packages_add)
+
+    if packages_remove:
+        event_manager.progress_update(
+            "Removing packages: %s" % str(packages_remove))
+        os_morphing_tools.uninstall_packages(packages_remove)
+
+    LOG.info("Post packages")
+    os_morphing_tools.post_packages_install()
+
+    event_manager.progress_update("Dismounting OS partitions")
+    os_mount_tools.dismount_os(other_mounted_dirs + [os_root_dir])

+ 62 - 62
coriolis/osmorphing/osmount/base.py

@@ -1,62 +1,62 @@
-import abc
-
-from oslo_log import log as logging
-import paramiko
-
-from coriolis import utils
-
-LOG = logging.getLogger(__name__)
-
-
-class BaseOSMountTools(object):
-    __metaclass__ = abc.ABCMeta
-
-    def __init__(self, connection_info, event_manager, ignore_devices):
-        self._event_manager = event_manager
-        self._ignore_devices = ignore_devices
-        self._connect(connection_info)
-
-    @abc.abstractmethod
-    def _connect(self, connection_info):
-        pass
-
-    @abc.abstractmethod
-    def get_connection(self):
-        pass
-
-    @abc.abstractmethod
-    def check_os(self):
-        pass
-
-    @abc.abstractmethod
-    def mount_os(self):
-        pass
-
-    @abc.abstractmethod
-    def dismount_os(self, dirs):
-        pass
-
-
-class BaseSSHOSMountTools(BaseOSMountTools):
-    def _connect(self, connection_info):
-        ip = connection_info["ip"]
-        port = connection_info.get("port", 22)
-        username = connection_info["username"]
-        pkey = connection_info.get("pkey")
-        password = connection_info.get("password")
-
-        LOG.info("Waiting for connectivity on host: %(ip)s:%(port)s",
-                 {"ip": ip, "port": port})
-        utils.wait_for_port_connectivity(ip, port)
-
-        self._event_manager.progress_update(
-            "Connecting to SSH host: %(ip)s:%(port)s" %
-            {"ip": ip, "port": port})
-        ssh = paramiko.SSHClient()
-        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-        ssh.connect(hostname=ip, port=port, username=username, pkey=pkey,
-                    password=password)
-        self._ssh = ssh
-
-    def get_connection(self):
-        return self._ssh
+import abc
+
+from oslo_log import log as logging
+import paramiko
+
+from coriolis import utils
+
+LOG = logging.getLogger(__name__)
+
+
+class BaseOSMountTools(object):
+    __metaclass__ = abc.ABCMeta
+
+    def __init__(self, connection_info, event_manager, ignore_devices):
+        self._event_manager = event_manager
+        self._ignore_devices = ignore_devices
+        self._connect(connection_info)
+
+    @abc.abstractmethod
+    def _connect(self, connection_info):
+        pass
+
+    @abc.abstractmethod
+    def get_connection(self):
+        pass
+
+    @abc.abstractmethod
+    def check_os(self):
+        pass
+
+    @abc.abstractmethod
+    def mount_os(self):
+        pass
+
+    @abc.abstractmethod
+    def dismount_os(self, dirs):
+        pass
+
+
+class BaseSSHOSMountTools(BaseOSMountTools):
+    def _connect(self, connection_info):
+        ip = connection_info["ip"]
+        port = connection_info.get("port", 22)
+        username = connection_info["username"]
+        pkey = connection_info.get("pkey")
+        password = connection_info.get("password")
+
+        LOG.info("Waiting for connectivity on host: %(ip)s:%(port)s",
+                 {"ip": ip, "port": port})
+        utils.wait_for_port_connectivity(ip, port)
+
+        self._event_manager.progress_update(
+            "Connecting to SSH host: %(ip)s:%(port)s" %
+            {"ip": ip, "port": port})
+        ssh = paramiko.SSHClient()
+        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        ssh.connect(hostname=ip, port=port, username=username, pkey=pkey,
+                    password=password)
+        self._ssh = ssh
+
+    def get_connection(self):
+        return self._ssh

+ 27 - 27
coriolis/osmorphing/osmount/factory.py

@@ -1,27 +1,27 @@
-import itertools
-
-from oslo_log import log as logging
-
-from coriolis import constants
-from coriolis import exception
-from coriolis.osmorphing.osmount import ubuntu
-from coriolis.osmorphing.osmount import windows
-
-LOG = logging.getLogger(__name__)
-
-
-def get_os_mount_tools(os_type, connection_info, event_manager,
-                       ignore_devices):
-    os_mount_tools = {constants.OS_TYPE_LINUX: [ubuntu.UbuntuOSMountTools],
-                      constants.OS_TYPE_WINDOWS: [windows.WindowsMountTools]}
-
-    if os_type and os_type not in os_mount_tools:
-        raise exception.CoriolisException("Unsupported OS type: %s" % os_type)
-
-    for cls in os_mount_tools.get(os_type,
-                                  itertools.chain(*os_mount_tools.values())):
-        tools = cls(connection_info, event_manager, ignore_devices)
-        LOG.debug("Testing OS mount tools: %s", cls.__name__)
-        if tools.check_os():
-            return tools
-    raise exception.CoriolisException("OS mount tools not found")
+import itertools
+
+from oslo_log import log as logging
+
+from coriolis import constants
+from coriolis import exception
+from coriolis.osmorphing.osmount import ubuntu
+from coriolis.osmorphing.osmount import windows
+
+LOG = logging.getLogger(__name__)
+
+
+def get_os_mount_tools(os_type, connection_info, event_manager,
+                       ignore_devices):
+    os_mount_tools = {constants.OS_TYPE_LINUX: [ubuntu.UbuntuOSMountTools],
+                      constants.OS_TYPE_WINDOWS: [windows.WindowsMountTools]}
+
+    if os_type and os_type not in os_mount_tools:
+        raise exception.CoriolisException("Unsupported OS type: %s" % os_type)
+
+    for cls in os_mount_tools.get(os_type,
+                                  itertools.chain(*os_mount_tools.values())):
+        tools = cls(connection_info, event_manager, ignore_devices)
+        LOG.debug("Testing OS mount tools: %s", cls.__name__)
+        if tools.check_os():
+            return tools
+    raise exception.CoriolisException("OS mount tools not found")

+ 125 - 125
coriolis/osmorphing/osmount/ubuntu.py

@@ -1,125 +1,125 @@
-import os
-import re
-
-from oslo_log import log as logging
-
-from coriolis import exception
-from coriolis.osmorphing.osmount import base
-from coriolis import utils
-
-LOG = logging.getLogger(__name__)
-
-
-class UbuntuOSMountTools(base.BaseSSHOSMountTools):
-    def check_os(self):
-        os_info = utils.get_linux_os_info(self._ssh)
-        if os_info and os_info[0] == 'Ubuntu':
-            return True
-
-    def _exec_cmd(self, cmd):
-        return utils.exec_ssh_cmd(self._ssh, cmd)
-
-    def _get_vgnames(self):
-        vg_names = []
-        vgscan_out_lines = self._exec_cmd(
-            "sudo vgscan").decode().split('\n')[1:-1]
-        for vgscan_out_line in vgscan_out_lines:
-            m = re.match(
-                r'\s*Found volume group "(.*)" using metadata type lvm2',
-                vgscan_out_line)
-            if m:
-                vg_names.append(m.groups()[0])
-        return vg_names
-
-    def _get_volume_block_devices(self):
-        volume_devs = self._exec_cmd(
-            "lsblk -lnao NAME").decode().split('\n')[:-1]
-        LOG.debug("All block devices: %s", str(volume_devs))
-
-        # Skip this instance's current root device (first in the list)
-        volume_devs = ["/dev/%s" % d for d in volume_devs if
-                       not re.match(r"^.*\d+$", d)][1:]
-
-        LOG.debug("Ignoring block devices: %s", self._ignore_devices)
-        volume_devs = [d for d in volume_devs if d
-                       not in self._ignore_devices]
-
-        LOG.info("Volume block devices: %s", volume_devs)
-        return volume_devs
-
-    def mount_os(self):
-        dev_paths = []
-        other_mounted_dirs = []
-
-        self._exec_cmd("sudo apt-get update -y")
-        self._exec_cmd("sudo apt-get install lvm2 -y")
-        self._exec_cmd("sudo modprobe dm-mod")
-
-        volume_devs = self._get_volume_block_devices()
-        for volume_dev in volume_devs:
-            self._exec_cmd("sudo partx -v -a %s || true" % volume_dev)
-            dev_paths += self._exec_cmd(
-                "sudo ls %s*" % volume_dev).decode().split('\n')[:-1]
-
-        for vg_name in self._get_vgnames():
-            self._exec_cmd("sudo vgchange -ay %s" % vg_name)
-            lvm_dev_paths = self._exec_cmd(
-                "sudo ls /dev/%s/*" % vg_name).decode().split('\n')[:-1]
-            dev_paths += lvm_dev_paths
-
-        valid_filesystems = ['ext2', 'ext3', 'ext4', 'xfs', 'btrfs']
-
-        dev_paths_to_mount = []
-        for dev_path in dev_paths:
-            fs_type = self._exec_cmd(
-                "sudo blkid -o value -s TYPE %s || true" %
-                dev_path).decode().split('\n')[0]
-            if fs_type in valid_filesystems:
-                utils.check_fs(self._ssh, fs_type, dev_path)
-                dev_paths_to_mount.append(dev_path)
-
-        os_root_dir = None
-        boot_dev_path = None
-        for dev_path in dev_paths_to_mount:
-            tmp_dir = self._exec_cmd('mktemp -d').decode().split('\n')[0]
-            self._exec_cmd('sudo mount %s %s' % (dev_path, tmp_dir))
-            dirs = self._exec_cmd('ls %s' % tmp_dir).decode().split('\n')
-
-            # TODO: better ways to check for a linux root?
-            if (not os_root_dir and 'etc' in dirs and 'bin' in dirs and
-                    'sbin' in dirs):
-                os_root_dir = tmp_dir
-                LOG.info("OS root device: %s", dev_path)
-            # TODO: better ways to check for a linux boot dir?
-            else:
-                # TODO: better ways to check for a linux boot dir?
-                if not boot_dev_path and ('grub' in dirs or 'grub2' in dirs):
-                    # Needs to be remounted under os_root_dir
-                    boot_dev_path = dev_path
-                    LOG.info("OS boot device: %s", dev_path)
-
-                self._exec_cmd('sudo umount %s' % tmp_dir)
-
-            if os_root_dir and boot_dev_path:
-                break
-
-        if not os_root_dir:
-            raise exception.OperatingSystemNotFound("root partition not found")
-
-        for dir in set(dirs).intersection(['proc', 'sys', 'dev', 'run']):
-            mount_dir = os.path.join(os_root_dir, dir)
-            self._exec_cmd(
-                'sudo mount -o bind /%(dir)s/ %(mount_dir)s' %
-                {'dir': dir, 'mount_dir': mount_dir})
-            other_mounted_dirs.append(mount_dir)
-
-        if boot_dev_path:
-            boot_dir = os.path.join(os_root_dir, 'boot')
-            self._exec_cmd('sudo mount %s %s' % (boot_dev_path, boot_dir))
-            other_mounted_dirs.append(boot_dir)
-
-        return os_root_dir, other_mounted_dirs
-
-    def dismount_os(self, dirs):
-        for dir in dirs:
-            self._exec_cmd('sudo umount %s' % dir)
+import os
+import re
+
+from oslo_log import log as logging
+
+from coriolis import exception
+from coriolis.osmorphing.osmount import base
+from coriolis import utils
+
+LOG = logging.getLogger(__name__)
+
+
+class UbuntuOSMountTools(base.BaseSSHOSMountTools):
+    def check_os(self):
+        os_info = utils.get_linux_os_info(self._ssh)
+        if os_info and os_info[0] == 'Ubuntu':
+            return True
+
+    def _exec_cmd(self, cmd):
+        return utils.exec_ssh_cmd(self._ssh, cmd)
+
+    def _get_vgnames(self):
+        vg_names = []
+        vgscan_out_lines = self._exec_cmd(
+            "sudo vgscan").decode().split('\n')[1:-1]
+        for vgscan_out_line in vgscan_out_lines:
+            m = re.match(
+                r'\s*Found volume group "(.*)" using metadata type lvm2',
+                vgscan_out_line)
+            if m:
+                vg_names.append(m.groups()[0])
+        return vg_names
+
+    def _get_volume_block_devices(self):
+        volume_devs = self._exec_cmd(
+            "lsblk -lnao NAME").decode().split('\n')[:-1]
+        LOG.debug("All block devices: %s", str(volume_devs))
+
+        # Skip this instance's current root device (first in the list)
+        volume_devs = ["/dev/%s" % d for d in volume_devs if
+                       not re.match(r"^.*\d+$", d)][1:]
+
+        LOG.debug("Ignoring block devices: %s", self._ignore_devices)
+        volume_devs = [d for d in volume_devs if d
+                       not in self._ignore_devices]
+
+        LOG.info("Volume block devices: %s", volume_devs)
+        return volume_devs
+
+    def mount_os(self):
+        dev_paths = []
+        other_mounted_dirs = []
+
+        self._exec_cmd("sudo apt-get update -y")
+        self._exec_cmd("sudo apt-get install lvm2 -y")
+        self._exec_cmd("sudo modprobe dm-mod")
+
+        volume_devs = self._get_volume_block_devices()
+        for volume_dev in volume_devs:
+            self._exec_cmd("sudo partx -v -a %s || true" % volume_dev)
+            dev_paths += self._exec_cmd(
+                "sudo ls %s*" % volume_dev).decode().split('\n')[:-1]
+
+        for vg_name in self._get_vgnames():
+            self._exec_cmd("sudo vgchange -ay %s" % vg_name)
+            lvm_dev_paths = self._exec_cmd(
+                "sudo ls /dev/%s/*" % vg_name).decode().split('\n')[:-1]
+            dev_paths += lvm_dev_paths
+
+        valid_filesystems = ['ext2', 'ext3', 'ext4', 'xfs', 'btrfs']
+
+        dev_paths_to_mount = []
+        for dev_path in dev_paths:
+            fs_type = self._exec_cmd(
+                "sudo blkid -o value -s TYPE %s || true" %
+                dev_path).decode().split('\n')[0]
+            if fs_type in valid_filesystems:
+                utils.check_fs(self._ssh, fs_type, dev_path)
+                dev_paths_to_mount.append(dev_path)
+
+        os_root_dir = None
+        boot_dev_path = None
+        for dev_path in dev_paths_to_mount:
+            tmp_dir = self._exec_cmd('mktemp -d').decode().split('\n')[0]
+            self._exec_cmd('sudo mount %s %s' % (dev_path, tmp_dir))
+            dirs = self._exec_cmd('ls %s' % tmp_dir).decode().split('\n')
+
+            # TODO: better ways to check for a linux root?
+            if (not os_root_dir and 'etc' in dirs and 'bin' in dirs and
+                    'sbin' in dirs):
+                os_root_dir = tmp_dir
+                LOG.info("OS root device: %s", dev_path)
+            # TODO: better ways to check for a linux boot dir?
+            else:
+                # TODO: better ways to check for a linux boot dir?
+                if not boot_dev_path and ('grub' in dirs or 'grub2' in dirs):
+                    # Needs to be remounted under os_root_dir
+                    boot_dev_path = dev_path
+                    LOG.info("OS boot device: %s", dev_path)
+
+                self._exec_cmd('sudo umount %s' % tmp_dir)
+
+            if os_root_dir and boot_dev_path:
+                break
+
+        if not os_root_dir:
+            raise exception.OperatingSystemNotFound("root partition not found")
+
+        for dir in set(dirs).intersection(['proc', 'sys', 'dev', 'run']):
+            mount_dir = os.path.join(os_root_dir, dir)
+            self._exec_cmd(
+                'sudo mount -o bind /%(dir)s/ %(mount_dir)s' %
+                {'dir': dir, 'mount_dir': mount_dir})
+            other_mounted_dirs.append(mount_dir)
+
+        if boot_dev_path:
+            boot_dir = os.path.join(os_root_dir, 'boot')
+            self._exec_cmd('sudo mount %s %s' % (boot_dev_path, boot_dir))
+            other_mounted_dirs.append(boot_dir)
+
+        return os_root_dir, other_mounted_dirs
+
+    def dismount_os(self, dirs):
+        for dir in dirs:
+            self._exec_cmd('sudo umount %s' % dir)

+ 94 - 94
coriolis/osmorphing/osmount/windows.py

@@ -1,94 +1,94 @@
-import os
-import re
-
-from oslo_log import log as logging
-
-from coriolis import exception
-from coriolis.osmorphing.osmount import base
-from coriolis import utils
-from coriolis import wsman
-
-LOG = logging.getLogger(__name__)
-
-
-class WindowsMountTools(base.BaseOSMountTools):
-    def _connect(self, connection_info):
-        host = connection_info["ip"]
-        port = connection_info.get("port", 5986)
-        username = connection_info["username"]
-        password = connection_info.get("password")
-        cert_pem = connection_info.get("cert_pem")
-        cert_key_pem = connection_info.get("cert_key_pem")
-        url = "https://%s:%s/wsman" % (host, port)
-
-        LOG.info("Connection info: %s", str(connection_info))
-
-        LOG.info("Waiting for connectivity on host: %(host)s:%(port)s",
-                 {"host": host, "port": port})
-        utils.wait_for_port_connectivity(host, port)
-
-        self._event_manager.progress_update(
-            "Connecting to WinRM host: %(host)s:%(port)s" %
-            {"host": host, "port": port})
-
-        conn = wsman.WSManConnection()
-        conn.connect(url=url, username=username, password=password,
-                     cert_pem=cert_pem, cert_key_pem=cert_key_pem)
-        self._conn = conn
-
-    def get_connection(self):
-        return self._conn
-
-    def check_os(self):
-        try:
-            version_info = self._conn.exec_ps_command(
-                "(get-ciminstance Win32_OperatingSystem).Caption")
-            LOG.debug("Windows version: %s", version_info)
-            return True
-        except exception.CoriolisException:
-            pass
-
-    def _refresh_storage(self):
-        self._conn.exec_ps_command(
-            "Update-HostStorageCache", ignore_stdout=True)
-
-    def _bring_all_disks_online(self):
-        LOG.info("Bringing offline disks online")
-        self._conn.exec_ps_command(
-            "Get-Disk |? IsOffline | Set-Disk -IsOffline $False",
-            ignore_stdout=True)
-
-    def _set_all_disks_rw_mode(self):
-        LOG.info("Setting RW mode on RO disks")
-        self._conn.exec_ps_command(
-            "Get-Disk |? IsReadOnly | Set-Disk -IsReadOnly $False",
-            ignore_stdout=True)
-
-    def _bring_disk_offline(self, drive_letter):
-        self._conn.exec_ps_command(
-            "Get-Volume |? DriveLetter -eq \"%s\" | Get-Partition | "
-            "Get-Disk | Set-Disk -IsOffline $True" % drive_letter,
-            ignore_stdout=True)
-
-    def _get_system_drive(self):
-        return self._conn.exec_ps_command("$env:SystemDrive")
-
-    def _get_fs_roots(self):
-        return self._conn.exec_ps_command(
-            "(get-psdrive -PSProvider FileSystem).Root").split(self._conn.EOL)
-
-    def mount_os(self):
-        self._refresh_storage()
-        self._bring_all_disks_online()
-        self._set_all_disks_rw_mode()
-        fs_roots = self._get_fs_roots()
-        system_drive = self._get_system_drive()
-
-        for fs_root in [r for r in fs_roots if not r[:-1] == system_drive]:
-            if self._conn.test_path("%sWindows\\System32" % fs_root):
-                return fs_root, []
-
-    def dismount_os(self, dirs):
-        for dir in dirs:
-            drive_letter = dir.split(":")[0]
-            self._bring_disk_offline(drive_letter)
+import os
+import re
+
+from oslo_log import log as logging
+
+from coriolis import exception
+from coriolis.osmorphing.osmount import base
+from coriolis import utils
+from coriolis import wsman
+
+LOG = logging.getLogger(__name__)
+
+
+class WindowsMountTools(base.BaseOSMountTools):
+    def _connect(self, connection_info):
+        host = connection_info["ip"]
+        port = connection_info.get("port", 5986)
+        username = connection_info["username"]
+        password = connection_info.get("password")
+        cert_pem = connection_info.get("cert_pem")
+        cert_key_pem = connection_info.get("cert_key_pem")
+        url = "https://%s:%s/wsman" % (host, port)
+
+        LOG.info("Connection info: %s", str(connection_info))
+
+        LOG.info("Waiting for connectivity on host: %(host)s:%(port)s",
+                 {"host": host, "port": port})
+        utils.wait_for_port_connectivity(host, port)
+
+        self._event_manager.progress_update(
+            "Connecting to WinRM host: %(host)s:%(port)s" %
+            {"host": host, "port": port})
+
+        conn = wsman.WSManConnection()
+        conn.connect(url=url, username=username, password=password,
+                     cert_pem=cert_pem, cert_key_pem=cert_key_pem)
+        self._conn = conn
+
+    def get_connection(self):
+        return self._conn
+
+    def check_os(self):
+        try:
+            version_info = self._conn.exec_ps_command(
+                "(get-ciminstance Win32_OperatingSystem).Caption")
+            LOG.debug("Windows version: %s", version_info)
+            return True
+        except exception.CoriolisException:
+            pass
+
+    def _refresh_storage(self):
+        self._conn.exec_ps_command(
+            "Update-HostStorageCache", ignore_stdout=True)
+
+    def _bring_all_disks_online(self):
+        LOG.info("Bringing offline disks online")
+        self._conn.exec_ps_command(
+            "Get-Disk |? IsOffline | Set-Disk -IsOffline $False",
+            ignore_stdout=True)
+
+    def _set_all_disks_rw_mode(self):
+        LOG.info("Setting RW mode on RO disks")
+        self._conn.exec_ps_command(
+            "Get-Disk |? IsReadOnly | Set-Disk -IsReadOnly $False",
+            ignore_stdout=True)
+
+    def _bring_disk_offline(self, drive_letter):
+        self._conn.exec_ps_command(
+            "Get-Volume |? DriveLetter -eq \"%s\" | Get-Partition | "
+            "Get-Disk | Set-Disk -IsOffline $True" % drive_letter,
+            ignore_stdout=True)
+
+    def _get_system_drive(self):
+        return self._conn.exec_ps_command("$env:SystemDrive")
+
+    def _get_fs_roots(self):
+        return self._conn.exec_ps_command(
+            "(get-psdrive -PSProvider FileSystem).Root").split(self._conn.EOL)
+
+    def mount_os(self):
+        self._refresh_storage()
+        self._bring_all_disks_online()
+        self._set_all_disks_rw_mode()
+        fs_roots = self._get_fs_roots()
+        system_drive = self._get_system_drive()
+
+        for fs_root in [r for r in fs_roots if not r[:-1] == system_drive]:
+            if self._conn.test_path("%sWindows\\System32" % fs_root):
+                return fs_root, []
+
+    def dismount_os(self, dirs):
+        for dir in dirs:
+            drive_letter = dir.split(":")[0]
+            self._bring_disk_offline(drive_letter)

+ 20 - 20
coriolis/osmorphing/ubuntu.py

@@ -1,20 +1,20 @@
-from coriolis import constants
-from coriolis.osmorphing import debian
-
-
-class UbuntuMorphingTools(debian.DebianMorphingTools):
-    _packages = {
-        (constants.HYPERVISOR_VMWARE, None): [("open-vm-tools", True)],
-        # TODO: sudo agt-get install linux-tool-<kernel release>
-        # linux-cloud-tools-<kernel release> -y
-        (constants.HYPERVISOR_HYPERV, None): [("hv-kvp-daemon-init", True)],
-        # TODO: add cloud-initramfs-growroot
-        (None, constants.PLATFORM_OPENSTACK): [("cloud-init", True)],
-    }
-
-    def _check_os(self):
-        config = self._read_config_file("etc/lsb-release", check_exists=True)
-        dist_id = config.get('DISTRIB_ID')
-        if dist_id == 'Ubuntu':
-            release = config.get('DISTRIB_RELEASE')
-            return (dist_id, release)
+from coriolis import constants
+from coriolis.osmorphing import debian
+
+
+class UbuntuMorphingTools(debian.DebianMorphingTools):
+    _packages = {
+        (constants.HYPERVISOR_VMWARE, None): [("open-vm-tools", True)],
+        # TODO: sudo agt-get install linux-tool-<kernel release>
+        # linux-cloud-tools-<kernel release> -y
+        (constants.HYPERVISOR_HYPERV, None): [("hv-kvp-daemon-init", True)],
+        # TODO: add cloud-initramfs-growroot
+        (None, constants.PLATFORM_OPENSTACK): [("cloud-init", True)],
+    }
+
+    def _check_os(self):
+        config = self._read_config_file("etc/lsb-release", check_exists=True)
+        dist_id = config.get('DISTRIB_ID')
+        if dist_id == 'Ubuntu':
+            release = config.get('DISTRIB_RELEASE')
+            return (dist_id, release)

+ 396 - 396
coriolis/osmorphing/windows.py

@@ -1,396 +1,396 @@
-import os
-import re
-import uuid
-
-from distutils import version
-from oslo_config import cfg
-from oslo_log import log as logging
-
-from coriolis import constants
-from coriolis import exception
-from coriolis.osmorphing import base
-
-opts = [
-    cfg.StrOpt('virtio_iso_url',
-               default='https://fedorapeople.org/groups/virt/virtio-win/'
-               'direct-downloads/stable-virtio/virtio-win.iso',
-               help="Location of the virtio-win ISO"),
-    cfg.StrOpt('cloudbaseinit_x64_url',
-               default="https://www.cloudbase.it/downloads/"
-               "CloudbaseInitSetup_x64.zip",
-               help="Location of the Cloudbase-Init ZIP for amd64 systems"),
-    cfg.StrOpt('cloudbaseinit_x86_url',
-               default="https://www.cloudbase.it/downloads/"
-               "CloudbaseInitSetup_x86.zip",
-               help="Location of the Cloudbase-Init ZIP for amd64 systems"),
-]
-
-CONF = cfg.CONF
-CONF.register_opts(opts, 'windows_images')
-
-LOG = logging.getLogger(__name__)
-
-SERVICE_START_AUTO = 2
-SERVICE_START_MANUAL = 3
-SERVICE_START_DISABLED = 4
-
-SERVICE_PATH_FORMAT = "HKLM:\\%s\\ControlSet001\\Services\\%s"
-CLOUDBASEINIT_SERVICE_NAME = "cloudbase-init"
-
-
-class WindowsMorphingTools(base.BaseOSMorphingTools):
-    def _check_os(self):
-        try:
-            (self._version_number,
-             self._edition_id,
-             self._installation_type,
-             self._product_name) = self._get_image_version_info()
-            return ('Windows', self._product_name)
-        except exception.CoriolisException as ex:
-            LOG.debug("Exception during OS detection: %s", ex)
-
-    def pre_packages_install(self):
-        if (not self._hypervisor or
-                self._hypervisor == constants.HYPERVISOR_KVM):
-            self._add_virtio_drivers()
-
-        if self._platform == constants.PLATFORM_OPENSTACK:
-            self._add_cloudbase_init()
-        else:
-            self._disable_cloudbase_init()
-
-    def set_net_config(self, nics_info, dhcp):
-        # TODO: implement
-        pass
-
-    def _get_dism_path(self):
-        return "c:\\Windows\\System32\\dism.exe"
-
-    def _get_sid(self):
-        sid = self._conn.exec_ps_command(
-            "(New-Object System.Security.Principal.NTAccount($ENV:USERNAME))."
-            "Translate([System.Security.Principal.SecurityIdentifier]).Value")
-        LOG.debug("Current user's SID: %s", sid)
-        return sid
-
-    def _grant_permissions(self, path, user, perm="(OI)(CI)F"):
-        self._conn.exec_command(
-            "icacls.exe", [path, "/grant", "%s:%s" % (user, perm)])
-
-    def _revoke_permissions(self, path, user):
-        self._conn.exec_command(
-            "icacls.exe", [path, "/remove", user])
-
-    def _load_registry_hive(self, subkey, path):
-        self._conn.exec_command("reg.exe", ["load", subkey, path])
-
-    def _unload_registry_hive(self, subkey):
-        self._conn.exec_command("reg.exe", ["unload", subkey])
-
-    def _get_ps_fl_value(self, data, name):
-        m = re.search(r'^%s\s*: (.*)$' % name, data, re.MULTILINE)
-        if m:
-            return m.groups()[0]
-
-    def _get_image_version_info(self):
-        key_name = str(uuid.uuid4())
-
-        self._load_registry_hive(
-            "HKLM\%s" % key_name,
-            "%sWindows\\System32\\config\\SOFTWARE" % self._os_root_dir)
-        try:
-            version_info_str = self._conn.exec_ps_command(
-                "Get-ItemProperty "
-                "'HKLM:\%s\Microsoft\Windows NT\CurrentVersion' "
-                "| select CurrentVersion, CurrentMajorVersionNumber, "
-                "CurrentMinorVersionNumber,  CurrentBuildNumber, "
-                "InstallationType, ProductName, EditionID | FL" %
-                key_name).replace(self._conn.EOL, os.linesep)
-        finally:
-            self._unload_registry_hive("HKLM\%s" % key_name)
-
-        version_info = {}
-        for n in ["CurrentVersion", "CurrentMajorVersionNumber",
-                  "CurrentMinorVersionNumber", "CurrentBuildNumber",
-                  "InstallationType", "ProductName", "EditionID"]:
-            version_info[n] = self._get_ps_fl_value(version_info_str, n)
-
-        if (not version_info["CurrentMajorVersionNumber"] and
-                not version_info["CurrentVersion"]):
-            raise exception.CoriolisException(
-                "Cannot find Windows version info")
-
-        if version_info["CurrentMajorVersionNumber"]:
-            version_str = "%s.%s.%s" % (
-                version_info["CurrentMajorVersionNumber"],
-                version_info["CurrentMinorVersionNumber"],
-                version_info["CurrentBuildNumber"])
-        else:
-            version_str = "%s.%s" % (
-                version_info["CurrentVersion"],
-                version_info["CurrentBuildNumber"])
-
-        return (version.LooseVersion(version_str),
-                version_info["EditionID"],
-                version_info["InstallationType"],
-                version_info["ProductName"])
-
-    def _add_dism_driver(self, driver_path):
-        LOG.info("Adding driver: %s" % driver_path)
-        dism_path = self._get_dism_path()
-        return self._conn.exec_command(
-            dism_path,
-            ["/add-driver", "/image:%s" % self._os_root_dir,
-             "/driver:%s" % driver_path, "/recurse", "/forceunsigned"])
-
-    def _mount_disk_image(self, path):
-        LOG.info("Mounting disk image: %s" % path)
-        return self._conn.exec_ps_command(
-            "(Mount-DiskImage '%s' -PassThru | Get-Volume).DriveLetter" %
-            path)
-
-    def _dismount_disk_image(self, path):
-        LOG.info("Unmounting disk image: %s" % path)
-        self._conn.exec_ps_command("Dismount-DiskImage '%s'" % path,
-                                   ignore_stdout=True)
-
-    def _add_virtio_drivers(self):
-        # TODO: add support for x86
-        arch = "amd64"
-
-        CLIENT = 1
-        SERVER = 2
-
-        # Ordered by version number
-        virtio_dirs = [
-            ("xp", version.LooseVersion("5.1"), CLIENT),
-            ("2k3", version.LooseVersion("5.2"), SERVER),
-            ("2k8", version.LooseVersion("6.0"), SERVER | CLIENT),
-            ("w7", version.LooseVersion("6.1"), CLIENT),
-            ("2k8R2", version.LooseVersion("6.1"), SERVER),
-            ("w8", version.LooseVersion("6.2"), CLIENT),
-            ("2k12", version.LooseVersion("6.2"), SERVER),
-            ("w8.1", version.LooseVersion("6.3"), CLIENT),
-            ("2k12R2", version.LooseVersion("6.3"), SERVER),
-            ("w10", version.LooseVersion("10.0"), SERVER | CLIENT),
-            ]
-
-        # The list of all possible editions is huge, this is a semplification
-        if "Server" in self._edition_id:
-            edition_type = SERVER
-        else:
-            edition_type = CLIENT
-
-        drivers = ["Balloon", "NetKVM", "qxl", "qxldod", "pvpanic", "viorng",
-                   "vioscsi", "vioserial", "viostor"]
-
-        self._event_manager.progress_update("Downloading virtio-win drivers")
-
-        virtio_iso_path = "c:\\virtio-win.iso"
-        self._conn.download_file(
-            CONF.windows_images.virtio_iso_url, virtio_iso_path)
-
-        self._event_manager.progress_update("Adding virtio-win drivers")
-
-        virtio_drive = self._mount_disk_image(virtio_iso_path)
-        try:
-            for virtio_dir, dir_version, dir_edition_type in reversed(
-                    virtio_dirs):
-                if self._version_number >= dir_version and (
-                        edition_type & dir_edition_type):
-                    path = "%s:\\Balloon\\%s\\%s" % (
-                        virtio_drive, virtio_dir, arch)
-                    if self._conn.test_path(path):
-                        break
-
-            driver_paths = ["%s:\\%s\\%s\\%s" % (
-                            virtio_drive, d, virtio_dir, arch)
-                            for d in drivers]
-
-            sid = self._get_sid()
-            # Fails on Nano Server without explicitly granting permissions
-            file_repo_path = ("%sWindows\System32\DriverStore\FileRepository" %
-                              self._os_root_dir)
-            self._grant_permissions(file_repo_path, "*%s" % sid)
-            try:
-                for driver_path in driver_paths:
-                    if self._conn.test_path(driver_path):
-                        self._add_dism_driver(driver_path)
-            finally:
-                self._revoke_permissions(file_repo_path, "*%s" % sid)
-        finally:
-            self._dismount_disk_image(virtio_iso_path)
-
-    def _expand_archive(self, path, destination):
-        LOG.info("Expanding archive \"%(path)s\" in \"%(destination)s\"",
-                 {"path": path, "destination": destination})
-        self._conn.exec_ps_command(
-            "if(([System.Management.Automation.PSTypeName]"
-            "'System.IO.Compression.ZipFile').Type -or "
-            "[System.Reflection.Assembly]::LoadWithPartialName("
-            "'System.IO.Compression.FileSystem')) {"
-            "[System.IO.Compression.ZipFile]::ExtractToDirectory('%(path)s', "
-            "'%(destination)s')} else {mkdir -Force '%(destination)s'; "
-            "$shell = New-Object -ComObject Shell.Application;"
-            "$shell.Namespace('%(destination)s').copyhere(($shell.NameSpace("
-            "'%(path)s')).items())}" %
-            {"path": path, "destination": destination},
-            ignore_stdout=True)
-
-    def _set_service_start_mode(self, key_name, service_name, start_mode):
-        LOG.info("Setting service start mode: %(service_name)s, "
-                 "%(start_mode)s", {"service_name": service_name,
-                                    "start_mode": start_mode})
-        registry_path = SERVICE_PATH_FORMAT % (key_name, service_name)
-        self._conn.exec_ps_command(
-            "Set-ItemProperty -Path '%(path)s' -Name 'Start' -Value "
-            "%(start_mode)s" %
-            {"path": registry_path, "start_mode": start_mode})
-
-    def _create_service(self, key_name, service_name, image_path,
-                        display_name, description,
-                        start_mode=SERVICE_START_AUTO,
-                        service_account="LocalSystem",
-                        depends_on=[]):
-        LOG.info("Creating service: %s", service_name)
-        registry_path = SERVICE_PATH_FORMAT % (key_name, service_name)
-        depends_on_ps = "@(%s)" % (",".join(["'%s'" % v for v in depends_on]))
-
-        self._conn.exec_ps_command(
-            "$ErrorActionPreference = 'Stop';"
-            "New-Item -Path '%(path)s' -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'ImagePath' -Value "
-            "'%(image_path)s' -Type ExpandString -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'DisplayName' -Value "
-            "'%(display_name)s' -Type String -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'Description' -Value "
-            "'%(description)s' -Type String -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'DependOnService' -Value "
-            "%(depends_on)s -Type MultiString -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'ObjectName' -Value "
-            "'%(service_account)s' -Type String -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'Start' -Value "
-            "%(start_mode)s -Type DWord -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'Type' -Value "
-            "16 -Type DWord -Force;"
-            "New-ItemProperty -Path '%(path)s' -Name 'ErrorControl' -Value "
-            "0 -Type DWord -Force" %
-            {"path": registry_path,
-             "image_path": image_path,
-             "display_name": display_name,
-             "description": description,
-             "depends_on": depends_on_ps,
-             "service_account": service_account,
-             "start_mode": start_mode},
-            ignore_stdout=True)
-
-    def _write_cloudbase_init_conf(self, cloudbaseinit_base_dir,
-                                   local_base_dir, com_port="COM1"):
-        LOG.info("Writing Cloudbase-Init configuration files")
-        conf_dir = "%s\\conf" % cloudbaseinit_base_dir
-        self._conn.exec_ps_command("mkdir '%s' -Force" % conf_dir,
-                                   ignore_stdout=True)
-
-        conf_file_path = "%s\\cloudbase-init.conf" % conf_dir
-
-        conf_content = (
-            "[DEFAULT]\n"
-            "username = Admin\n"
-            "groups = Administrators\n"
-            "inject_user_password = true\n"
-            "config_drive_raw_hhd = true\n"
-            "config_drive_cdrom = true\n"
-            "config_drive_vfat = true\n"
-            "bsdtar_path = %(bin_path)s\\bsdtar.exe\n"
-            "mtools_path = %(bin_path)s\n"
-            "logdir = %(log_path)s\n"
-            "logfile = cloudbase-init.log\n"
-            "default_log_levels = "
-            "comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN\n"
-            "mtu_use_dhcp_config = true\n"
-            "ntp_use_dhcp_config = true\n"
-            "allow_reboot = true\n"
-            "debug = true\n"
-            "logging_serial_port_settings = %(com_port)s,115200,N,8\n" %
-            {"bin_path": "%s\\Bin" % local_base_dir,
-             "log_path": "%s\\Log" % local_base_dir,
-             "com_port": com_port})
-
-        self._conn.write_file(conf_file_path, conf_content.encode())
-
-    def _check_cloudbase_init_exists(self, key_name):
-        reg_service_path = (SERVICE_PATH_FORMAT %
-                            (key_name, CLOUDBASEINIT_SERVICE_NAME))
-        return self._conn.exec_ps_command(
-            "Test-Path %s" % reg_service_path) == "True"
-
-    def _disable_cloudbase_init(self):
-        key_name = str(uuid.uuid4())
-        self._load_registry_hive(
-            "HKLM\%s" % key_name,
-            "%sWindows\\System32\\config\\SYSTEM" % self._os_root_dir)
-        try:
-            if self._check_cloudbase_init_exists(key_name):
-                self._event_manager.progress_update(
-                    "Disabling cloudbase-init")
-                self._set_service_start_mode(
-                    key_name, CLOUDBASEINIT_SERVICE_NAME,
-                    SERVICE_START_DISABLED)
-        finally:
-            self._unload_registry_hive("HKLM\%s" % key_name)
-
-    def _add_cloudbase_init(self):
-        # TODO: add support for x86
-        arch = "amd64"
-        arch_url_map = {"amd64": CONF.windows_images.cloudbaseinit_x64_url,
-                        "x86": CONF.windows_images.cloudbaseinit_x86_url}
-
-        self._event_manager.progress_update("Adding cloudbase-init")
-
-        key_name = str(uuid.uuid4())
-        self._load_registry_hive(
-            "HKLM\%s" % key_name,
-            "%sWindows\\System32\\config\\SYSTEM" % self._os_root_dir)
-        try:
-            if self._check_cloudbase_init_exists(key_name):
-                self._event_manager.progress_update(
-                    "Enabling cloudbase-init")
-                self._set_service_start_mode(
-                    key_name, CLOUDBASEINIT_SERVICE_NAME, SERVICE_START_AUTO)
-            else:
-                cloudbaseinit_zip_path = "c:\\cloudbaseinit.zip"
-                cloudbaseinit_base_dir = "%sCloudbase-Init" % self._os_root_dir
-
-                self._event_manager.progress_update(
-                    "Downloading cloudbase-init")
-                self._conn.download_file(arch_url_map[arch],
-                                         cloudbaseinit_zip_path)
-
-                self._event_manager.progress_update(
-                    "Installing cloudbase-init")
-                self._expand_archive(cloudbaseinit_zip_path,
-                                     cloudbaseinit_base_dir)
-
-                log_dir = "%s\\Log" % cloudbaseinit_base_dir
-                self._conn.exec_ps_command("mkdir '%s' -Force" % log_dir,
-                                           ignore_stdout=True)
-
-                local_base_dir = "C%s" % cloudbaseinit_base_dir[1:]
-                self._write_cloudbase_init_conf(
-                    cloudbaseinit_base_dir, local_base_dir)
-
-                image_path = (
-                    '""""%(path)s\\Bin\\OpenStackService.exe"""" '
-                    'cloudbase-init """"%(path)s\\Python\\Python.exe"""" -c '
-                    '""""from cloudbaseinit import shell;shell.main()"""" '
-                    '--config-file """"%(path)s\\conf\\cloudbase-init.conf""""'
-                    % {'path': local_base_dir})
-
-                self._create_service(
-                    key_name=key_name,
-                    service_name=CLOUDBASEINIT_SERVICE_NAME,
-                    image_path=image_path,
-                    display_name="Cloud Initialization Service",
-                    description="Service wrapper for cloudbase-init")
-        finally:
-            self._unload_registry_hive("HKLM\%s" % key_name)
+import os
+import re
+import uuid
+
+from distutils import version
+from oslo_config import cfg
+from oslo_log import log as logging
+
+from coriolis import constants
+from coriolis import exception
+from coriolis.osmorphing import base
+
+opts = [
+    cfg.StrOpt('virtio_iso_url',
+               default='https://fedorapeople.org/groups/virt/virtio-win/'
+               'direct-downloads/stable-virtio/virtio-win.iso',
+               help="Location of the virtio-win ISO"),
+    cfg.StrOpt('cloudbaseinit_x64_url',
+               default="https://www.cloudbase.it/downloads/"
+               "CloudbaseInitSetup_x64.zip",
+               help="Location of the Cloudbase-Init ZIP for amd64 systems"),
+    cfg.StrOpt('cloudbaseinit_x86_url',
+               default="https://www.cloudbase.it/downloads/"
+               "CloudbaseInitSetup_x86.zip",
+               help="Location of the Cloudbase-Init ZIP for amd64 systems"),
+]
+
+CONF = cfg.CONF
+CONF.register_opts(opts, 'windows_images')
+
+LOG = logging.getLogger(__name__)
+
+SERVICE_START_AUTO = 2
+SERVICE_START_MANUAL = 3
+SERVICE_START_DISABLED = 4
+
+SERVICE_PATH_FORMAT = "HKLM:\\%s\\ControlSet001\\Services\\%s"
+CLOUDBASEINIT_SERVICE_NAME = "cloudbase-init"
+
+
+class WindowsMorphingTools(base.BaseOSMorphingTools):
+    def _check_os(self):
+        try:
+            (self._version_number,
+             self._edition_id,
+             self._installation_type,
+             self._product_name) = self._get_image_version_info()
+            return ('Windows', self._product_name)
+        except exception.CoriolisException as ex:
+            LOG.debug("Exception during OS detection: %s", ex)
+
+    def pre_packages_install(self):
+        if (not self._hypervisor or
+                self._hypervisor == constants.HYPERVISOR_KVM):
+            self._add_virtio_drivers()
+
+        if self._platform == constants.PLATFORM_OPENSTACK:
+            self._add_cloudbase_init()
+        else:
+            self._disable_cloudbase_init()
+
+    def set_net_config(self, nics_info, dhcp):
+        # TODO: implement
+        pass
+
+    def _get_dism_path(self):
+        return "c:\\Windows\\System32\\dism.exe"
+
+    def _get_sid(self):
+        sid = self._conn.exec_ps_command(
+            "(New-Object System.Security.Principal.NTAccount($ENV:USERNAME))."
+            "Translate([System.Security.Principal.SecurityIdentifier]).Value")
+        LOG.debug("Current user's SID: %s", sid)
+        return sid
+
+    def _grant_permissions(self, path, user, perm="(OI)(CI)F"):
+        self._conn.exec_command(
+            "icacls.exe", [path, "/grant", "%s:%s" % (user, perm)])
+
+    def _revoke_permissions(self, path, user):
+        self._conn.exec_command(
+            "icacls.exe", [path, "/remove", user])
+
+    def _load_registry_hive(self, subkey, path):
+        self._conn.exec_command("reg.exe", ["load", subkey, path])
+
+    def _unload_registry_hive(self, subkey):
+        self._conn.exec_command("reg.exe", ["unload", subkey])
+
+    def _get_ps_fl_value(self, data, name):
+        m = re.search(r'^%s\s*: (.*)$' % name, data, re.MULTILINE)
+        if m:
+            return m.groups()[0]
+
+    def _get_image_version_info(self):
+        key_name = str(uuid.uuid4())
+
+        self._load_registry_hive(
+            "HKLM\%s" % key_name,
+            "%sWindows\\System32\\config\\SOFTWARE" % self._os_root_dir)
+        try:
+            version_info_str = self._conn.exec_ps_command(
+                "Get-ItemProperty "
+                "'HKLM:\%s\Microsoft\Windows NT\CurrentVersion' "
+                "| select CurrentVersion, CurrentMajorVersionNumber, "
+                "CurrentMinorVersionNumber,  CurrentBuildNumber, "
+                "InstallationType, ProductName, EditionID | FL" %
+                key_name).replace(self._conn.EOL, os.linesep)
+        finally:
+            self._unload_registry_hive("HKLM\%s" % key_name)
+
+        version_info = {}
+        for n in ["CurrentVersion", "CurrentMajorVersionNumber",
+                  "CurrentMinorVersionNumber", "CurrentBuildNumber",
+                  "InstallationType", "ProductName", "EditionID"]:
+            version_info[n] = self._get_ps_fl_value(version_info_str, n)
+
+        if (not version_info["CurrentMajorVersionNumber"] and
+                not version_info["CurrentVersion"]):
+            raise exception.CoriolisException(
+                "Cannot find Windows version info")
+
+        if version_info["CurrentMajorVersionNumber"]:
+            version_str = "%s.%s.%s" % (
+                version_info["CurrentMajorVersionNumber"],
+                version_info["CurrentMinorVersionNumber"],
+                version_info["CurrentBuildNumber"])
+        else:
+            version_str = "%s.%s" % (
+                version_info["CurrentVersion"],
+                version_info["CurrentBuildNumber"])
+
+        return (version.LooseVersion(version_str),
+                version_info["EditionID"],
+                version_info["InstallationType"],
+                version_info["ProductName"])
+
+    def _add_dism_driver(self, driver_path):
+        LOG.info("Adding driver: %s" % driver_path)
+        dism_path = self._get_dism_path()
+        return self._conn.exec_command(
+            dism_path,
+            ["/add-driver", "/image:%s" % self._os_root_dir,
+             "/driver:%s" % driver_path, "/recurse", "/forceunsigned"])
+
+    def _mount_disk_image(self, path):
+        LOG.info("Mounting disk image: %s" % path)
+        return self._conn.exec_ps_command(
+            "(Mount-DiskImage '%s' -PassThru | Get-Volume).DriveLetter" %
+            path)
+
+    def _dismount_disk_image(self, path):
+        LOG.info("Unmounting disk image: %s" % path)
+        self._conn.exec_ps_command("Dismount-DiskImage '%s'" % path,
+                                   ignore_stdout=True)
+
+    def _add_virtio_drivers(self):
+        # TODO: add support for x86
+        arch = "amd64"
+
+        CLIENT = 1
+        SERVER = 2
+
+        # Ordered by version number
+        virtio_dirs = [
+            ("xp", version.LooseVersion("5.1"), CLIENT),
+            ("2k3", version.LooseVersion("5.2"), SERVER),
+            ("2k8", version.LooseVersion("6.0"), SERVER | CLIENT),
+            ("w7", version.LooseVersion("6.1"), CLIENT),
+            ("2k8R2", version.LooseVersion("6.1"), SERVER),
+            ("w8", version.LooseVersion("6.2"), CLIENT),
+            ("2k12", version.LooseVersion("6.2"), SERVER),
+            ("w8.1", version.LooseVersion("6.3"), CLIENT),
+            ("2k12R2", version.LooseVersion("6.3"), SERVER),
+            ("w10", version.LooseVersion("10.0"), SERVER | CLIENT),
+            ]
+
+        # The list of all possible editions is huge, this is a semplification
+        if "Server" in self._edition_id:
+            edition_type = SERVER
+        else:
+            edition_type = CLIENT
+
+        drivers = ["Balloon", "NetKVM", "qxl", "qxldod", "pvpanic", "viorng",
+                   "vioscsi", "vioserial", "viostor"]
+
+        self._event_manager.progress_update("Downloading virtio-win drivers")
+
+        virtio_iso_path = "c:\\virtio-win.iso"
+        self._conn.download_file(
+            CONF.windows_images.virtio_iso_url, virtio_iso_path)
+
+        self._event_manager.progress_update("Adding virtio-win drivers")
+
+        virtio_drive = self._mount_disk_image(virtio_iso_path)
+        try:
+            for virtio_dir, dir_version, dir_edition_type in reversed(
+                    virtio_dirs):
+                if self._version_number >= dir_version and (
+                        edition_type & dir_edition_type):
+                    path = "%s:\\Balloon\\%s\\%s" % (
+                        virtio_drive, virtio_dir, arch)
+                    if self._conn.test_path(path):
+                        break
+
+            driver_paths = ["%s:\\%s\\%s\\%s" % (
+                            virtio_drive, d, virtio_dir, arch)
+                            for d in drivers]
+
+            sid = self._get_sid()
+            # Fails on Nano Server without explicitly granting permissions
+            file_repo_path = ("%sWindows\System32\DriverStore\FileRepository" %
+                              self._os_root_dir)
+            self._grant_permissions(file_repo_path, "*%s" % sid)
+            try:
+                for driver_path in driver_paths:
+                    if self._conn.test_path(driver_path):
+                        self._add_dism_driver(driver_path)
+            finally:
+                self._revoke_permissions(file_repo_path, "*%s" % sid)
+        finally:
+            self._dismount_disk_image(virtio_iso_path)
+
+    def _expand_archive(self, path, destination):
+        LOG.info("Expanding archive \"%(path)s\" in \"%(destination)s\"",
+                 {"path": path, "destination": destination})
+        self._conn.exec_ps_command(
+            "if(([System.Management.Automation.PSTypeName]"
+            "'System.IO.Compression.ZipFile').Type -or "
+            "[System.Reflection.Assembly]::LoadWithPartialName("
+            "'System.IO.Compression.FileSystem')) {"
+            "[System.IO.Compression.ZipFile]::ExtractToDirectory('%(path)s', "
+            "'%(destination)s')} else {mkdir -Force '%(destination)s'; "
+            "$shell = New-Object -ComObject Shell.Application;"
+            "$shell.Namespace('%(destination)s').copyhere(($shell.NameSpace("
+            "'%(path)s')).items())}" %
+            {"path": path, "destination": destination},
+            ignore_stdout=True)
+
+    def _set_service_start_mode(self, key_name, service_name, start_mode):
+        LOG.info("Setting service start mode: %(service_name)s, "
+                 "%(start_mode)s", {"service_name": service_name,
+                                    "start_mode": start_mode})
+        registry_path = SERVICE_PATH_FORMAT % (key_name, service_name)
+        self._conn.exec_ps_command(
+            "Set-ItemProperty -Path '%(path)s' -Name 'Start' -Value "
+            "%(start_mode)s" %
+            {"path": registry_path, "start_mode": start_mode})
+
+    def _create_service(self, key_name, service_name, image_path,
+                        display_name, description,
+                        start_mode=SERVICE_START_AUTO,
+                        service_account="LocalSystem",
+                        depends_on=[]):
+        LOG.info("Creating service: %s", service_name)
+        registry_path = SERVICE_PATH_FORMAT % (key_name, service_name)
+        depends_on_ps = "@(%s)" % (",".join(["'%s'" % v for v in depends_on]))
+
+        self._conn.exec_ps_command(
+            "$ErrorActionPreference = 'Stop';"
+            "New-Item -Path '%(path)s' -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'ImagePath' -Value "
+            "'%(image_path)s' -Type ExpandString -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'DisplayName' -Value "
+            "'%(display_name)s' -Type String -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'Description' -Value "
+            "'%(description)s' -Type String -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'DependOnService' -Value "
+            "%(depends_on)s -Type MultiString -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'ObjectName' -Value "
+            "'%(service_account)s' -Type String -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'Start' -Value "
+            "%(start_mode)s -Type DWord -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'Type' -Value "
+            "16 -Type DWord -Force;"
+            "New-ItemProperty -Path '%(path)s' -Name 'ErrorControl' -Value "
+            "0 -Type DWord -Force" %
+            {"path": registry_path,
+             "image_path": image_path,
+             "display_name": display_name,
+             "description": description,
+             "depends_on": depends_on_ps,
+             "service_account": service_account,
+             "start_mode": start_mode},
+            ignore_stdout=True)
+
+    def _write_cloudbase_init_conf(self, cloudbaseinit_base_dir,
+                                   local_base_dir, com_port="COM1"):
+        LOG.info("Writing Cloudbase-Init configuration files")
+        conf_dir = "%s\\conf" % cloudbaseinit_base_dir
+        self._conn.exec_ps_command("mkdir '%s' -Force" % conf_dir,
+                                   ignore_stdout=True)
+
+        conf_file_path = "%s\\cloudbase-init.conf" % conf_dir
+
+        conf_content = (
+            "[DEFAULT]\n"
+            "username = Admin\n"
+            "groups = Administrators\n"
+            "inject_user_password = true\n"
+            "config_drive_raw_hhd = true\n"
+            "config_drive_cdrom = true\n"
+            "config_drive_vfat = true\n"
+            "bsdtar_path = %(bin_path)s\\bsdtar.exe\n"
+            "mtools_path = %(bin_path)s\n"
+            "logdir = %(log_path)s\n"
+            "logfile = cloudbase-init.log\n"
+            "default_log_levels = "
+            "comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN\n"
+            "mtu_use_dhcp_config = true\n"
+            "ntp_use_dhcp_config = true\n"
+            "allow_reboot = true\n"
+            "debug = true\n"
+            "logging_serial_port_settings = %(com_port)s,115200,N,8\n" %
+            {"bin_path": "%s\\Bin" % local_base_dir,
+             "log_path": "%s\\Log" % local_base_dir,
+             "com_port": com_port})
+
+        self._conn.write_file(conf_file_path, conf_content.encode())
+
+    def _check_cloudbase_init_exists(self, key_name):
+        reg_service_path = (SERVICE_PATH_FORMAT %
+                            (key_name, CLOUDBASEINIT_SERVICE_NAME))
+        return self._conn.exec_ps_command(
+            "Test-Path %s" % reg_service_path) == "True"
+
+    def _disable_cloudbase_init(self):
+        key_name = str(uuid.uuid4())
+        self._load_registry_hive(
+            "HKLM\%s" % key_name,
+            "%sWindows\\System32\\config\\SYSTEM" % self._os_root_dir)
+        try:
+            if self._check_cloudbase_init_exists(key_name):
+                self._event_manager.progress_update(
+                    "Disabling cloudbase-init")
+                self._set_service_start_mode(
+                    key_name, CLOUDBASEINIT_SERVICE_NAME,
+                    SERVICE_START_DISABLED)
+        finally:
+            self._unload_registry_hive("HKLM\%s" % key_name)
+
+    def _add_cloudbase_init(self):
+        # TODO: add support for x86
+        arch = "amd64"
+        arch_url_map = {"amd64": CONF.windows_images.cloudbaseinit_x64_url,
+                        "x86": CONF.windows_images.cloudbaseinit_x86_url}
+
+        self._event_manager.progress_update("Adding cloudbase-init")
+
+        key_name = str(uuid.uuid4())
+        self._load_registry_hive(
+            "HKLM\%s" % key_name,
+            "%sWindows\\System32\\config\\SYSTEM" % self._os_root_dir)
+        try:
+            if self._check_cloudbase_init_exists(key_name):
+                self._event_manager.progress_update(
+                    "Enabling cloudbase-init")
+                self._set_service_start_mode(
+                    key_name, CLOUDBASEINIT_SERVICE_NAME, SERVICE_START_AUTO)
+            else:
+                cloudbaseinit_zip_path = "c:\\cloudbaseinit.zip"
+                cloudbaseinit_base_dir = "%sCloudbase-Init" % self._os_root_dir
+
+                self._event_manager.progress_update(
+                    "Downloading cloudbase-init")
+                self._conn.download_file(arch_url_map[arch],
+                                         cloudbaseinit_zip_path)
+
+                self._event_manager.progress_update(
+                    "Installing cloudbase-init")
+                self._expand_archive(cloudbaseinit_zip_path,
+                                     cloudbaseinit_base_dir)
+
+                log_dir = "%s\\Log" % cloudbaseinit_base_dir
+                self._conn.exec_ps_command("mkdir '%s' -Force" % log_dir,
+                                           ignore_stdout=True)
+
+                local_base_dir = "C%s" % cloudbaseinit_base_dir[1:]
+                self._write_cloudbase_init_conf(
+                    cloudbaseinit_base_dir, local_base_dir)
+
+                image_path = (
+                    '""""%(path)s\\Bin\\OpenStackService.exe"""" '
+                    'cloudbase-init """"%(path)s\\Python\\Python.exe"""" -c '
+                    '""""from cloudbaseinit import shell;shell.main()"""" '
+                    '--config-file """"%(path)s\\conf\\cloudbase-init.conf""""'
+                    % {'path': local_base_dir})
+
+                self._create_service(
+                    key_name=key_name,
+                    service_name=CLOUDBASEINIT_SERVICE_NAME,
+                    image_path=image_path,
+                    display_name="Cloud Initialization Service",
+                    description="Service wrapper for cloudbase-init")
+        finally:
+            self._unload_registry_hive("HKLM\%s" % key_name)

+ 294 - 294
coriolis/providers/vmware_vsphere/__init__.py

@@ -1,294 +1,294 @@
-import os
-import sys
-import time
-from urllib import request
-
-import eventlet
-from oslo_config import cfg
-from oslo_log import log as logging
-from pyVim import connect
-from pyVmomi import vim
-
-from coriolis import constants
-from coriolis import exception
-from coriolis.providers import base
-from coriolis.providers.vmware_vsphere import guestid
-from coriolis import utils
-
-vmware_vsphere_opts = [
-    cfg.StrOpt('vdiskmanager_path',
-               default='vmware-vdiskmanager',
-               help='The vmware-vdiskmanager path.'),
-]
-
-CONF = cfg.CONF
-CONF.register_opts(vmware_vsphere_opts, 'vmware_vsphere')
-
-LOG = logging.getLogger(__name__)
-
-
-class ExportProvider(base.BaseExportProvider):
-    def validate_connection_info(self, connection_info):
-        return True
-
-    @utils.retry_on_error()
-    def _convert_disk_type(self, disk_path, target_disk_path, target_type=0):
-        utils.exec_process([CONF.vmware_vsphere.vdiskmanager_path, "-r",
-                            disk_path, "-t", str(target_type),
-                            target_disk_path])
-
-    def _wait_for_task(self, task):
-        while task.info.state not in [vim.TaskInfo.State.success,
-                                      vim.TaskInfo.State.error]:
-            time.sleep(.1)
-        if task.info.state == vim.TaskInfo.State.error:
-            raise exception.CoriolisException(task.info.error.msg)
-
-    @utils.retry_on_error()
-    def _connect(self, host, username, password, port, context):
-        LOG.info("Connecting to: %s:%s" % (host, port))
-        return connect.SmartConnect(
-            host=host,
-            user=username,
-            pwd=password,
-            port=port,
-            sslContext=context)
-
-    def _wait_for_vm_status(self, vm, status, max_wait=120):
-        i = 0
-        while i < max_wait and vm.runtime.powerState != status:
-            time.sleep(1)
-            i += 1
-        return i < max_wait
-
-    @utils.retry_on_error()
-    def _get_vm_info(self, si, instance_name):
-
-        LOG.info("Retrieving data for VM: %s" % instance_name)
-
-        # TODO: provide path selection
-        datacenter = si.content.rootFolder.childEntity[0]
-        vms = datacenter.vmFolder.childEntity
-        vm = [vm for vm in vms if vm.name == instance_name][0]
-
-        firmware_type_map = {
-            vim.vm.GuestOsDescriptor.FirmwareType.bios: 'BIOS',
-            vim.vm.GuestOsDescriptor.FirmwareType.efi: 'EFI'}
-
-        vm_info = {
-            'num_cpu': vm.config.hardware.numCPU,
-            'num_cores_per_socket': vm.config.hardware.numCoresPerSocket,
-            'memory_mb':  vm.config.hardware.memoryMB,
-            'firmware_type':  firmware_type_map[vm.config.firmware],
-            'nested_virtualization': vm.config.nestedHVEnabled,
-            'dynamic_memory_enabled':
-                not vm.config.memoryReservationLockedToMax,
-            'name': vm.config.name,
-            'guest_id': vm.config.guestId,
-            'os_type': guestid.GUEST_ID_OS_TYPE_MAP.get(vm.config.guestId),
-            'id': vm._moId,
-        }
-
-        LOG.info("vm info: %s" % str(vm_info))
-
-        if vm.runtime.powerState != vim.VirtualMachinePowerState.poweredOff:
-            power_off = True
-            if (vm.guest.toolsRunningStatus !=
-                    vim.vm.GuestInfo.ToolsRunningStatus.guestToolsNotRunning):
-                self._event_manager.progress_update("Shutting down guest OS")
-                vm.ShutdownGuest()
-                if self._wait_for_vm_status(
-                        vm, vim.VirtualMachinePowerState.poweredOff):
-                    power_off = False
-
-            if power_off:
-                self._event_manager.progress_update(
-                    "Powering off the virtual machine")
-                task = vm.PowerOff()
-                self._wait_for_task(task)
-
-        disk_ctrls = []
-        devices = [d for d in vm.config.hardware.device if
-                   isinstance(d, vim.vm.device.VirtualController)]
-        for device in devices:
-            ctrl_type = None
-            if isinstance(device, vim.vm.device.VirtualPCIController):
-                ctrl_type = "PCI"
-            elif isinstance(device, vim.vm.device.VirtualSIOController):
-                ctrl_type = "SIO"
-            elif isinstance(device, vim.vm.device.VirtualIDEController):
-                ctrl_type = "IDE"
-            elif isinstance(device, vim.vm.device.VirtualSATAController):
-                ctrl_type = "SATA"
-            elif isinstance(device, vim.vm.device.VirtualSCSIController):
-                ctrl_type = "SCSI"
-            else:
-                continue
-            disk_ctrls.append({'id': device.key, 'type': ctrl_type,
-                               'bus_number': device.busNumber})
-
-        disks = []
-        devices = [d for d in vm.config.hardware.device if
-                   isinstance(d, vim.vm.device.VirtualDisk)]
-        for device in devices:
-            disks.append({'size': device.capacityInBytes,
-                          'address': device.unitNumber,
-                          'id': device.key,
-                          'controller_id': device.controllerKey})
-
-        cdroms = []
-        devices = [d for d in vm.config.hardware.device if
-                   isinstance(d, vim.vm.device.VirtualCdrom)]
-        for device in devices:
-            cdroms.append({'address': device.unitNumber, 'id': device.key,
-                           'controller_id': device.controllerKey})
-
-        floppy = []
-        devices = [d for d in vm.config.hardware.device if
-                   isinstance(d, vim.vm.device.VirtualFloppy)]
-        for device in devices:
-            floppy.append({'address': device.unitNumber, 'id': device.key,
-                           'controller_id': device.controllerKey})
-
-        nics = []
-        devices = [d for d in vm.config.hardware.device if
-                   isinstance(d, vim.vm.device.VirtualEthernetCard)]
-        for device in devices:
-            nics.append({'mac_address': device.macAddress, 'id': device.key,
-                         'name': device.deviceInfo.label,
-                         'network_name': device.backing.network.name})
-
-        serial_ports = []
-        devices = [d for d in vm.config.hardware.device if
-                   isinstance(d, vim.vm.device.VirtualSerialPort)]
-        for device in devices:
-            serial_ports.append({'id': device.key})
-
-        boot_order = []
-        for boot_device in vm.config.bootOptions.bootOrder:
-            if isinstance(boot_device, vim.vm.BootOptions.BootableDiskDevice):
-                boot_order.append({"type": "disk",
-                                   "id": boot_device.deviceKey})
-            elif isinstance(boot_device,
-                            vim.vm.BootOptions.BootableCdromDevice):
-                boot_order.append({"type": "cdrom", "id": None})
-            elif isinstance.append(boot_device,
-                                   vim.vm.BootOptions.BootableEthernetDevice):
-                boot_order.append({"type": "ethernet",
-                                   "id": boot_device.deviceKey})
-            elif isinstance(boot_device,
-                            vim.vm.BootOptions.BootableFloppyDevice):
-                boot_order.append({"type": "floppy", "id": None})
-
-        vm_info["devices"] = {
-            "nics": nics,
-            "controllers": disk_ctrls,
-            "disks": disks,
-            "cdroms": cdroms,
-            "floppy": floppy,
-        }
-        vm_info["boot_order"] = boot_order
-
-        return vm_info, vm
-
-    @utils.retry_on_error()
-    def _export_disks(self, vm, export_path, context):
-        disk_paths = []
-        lease = vm.ExportVm()
-        while True:
-            if lease.state == vim.HttpNfcLease.State.ready:
-                try:
-                    tot_downloaded_bytes = 0
-                    for du in [du for du in lease.info.deviceUrl if du.disk]:
-                        # Key format: '/vm-70/VirtualLsiLogicController0:0'
-                        ctrl_str, address = du.key[
-                            du.key.rindex('/') + 1:].split(':')
-
-                        def _get_class_name(obj):
-                            return obj.__class__.__name__.split('.')[-1]
-
-                        for i, ctrl in enumerate(
-                            [d for d in vm.config.hardware.device if
-                             isinstance(
-                                d, vim.vm.device.VirtualController) and
-                                ctrl_str.startswith(_get_class_name(d))]):
-                            if int(ctrl_str[len(_get_class_name(ctrl)):]) == i:
-                                disk_key = [
-                                    d for d in vm.config.hardware.device if
-                                    isinstance(
-                                        d, vim.vm.device.VirtualDisk) and
-                                    d.controllerKey == ctrl.key and
-                                    d.unitNumber == int(address)][0].key
-                                break
-
-                        response = request.urlopen(du.url, context=context)
-                        path = os.path.join(export_path, du.targetId)
-                        disk_paths.append({'path': path, 'id': disk_key})
-
-                        LOG.info("Downloading: %s" % path)
-                        with open(path, 'wb') as f:
-                            while True:
-                                chunk = response.read(1024 * 1024)
-                                if not chunk:
-                                    break
-                                tot_downloaded_bytes += len(chunk)
-                                f.write(chunk)
-                                lease.HttpNfcLeaseProgress(
-                                    int(tot_downloaded_bytes * 100 /
-                                        (lease.info.totalDiskCapacityInKB *
-                                         1024)))
-
-                    lease.HttpNfcLeaseComplete()
-                    return disk_paths
-                except:
-                    lease.HttpNfcLeaseAbort()
-                    raise
-            elif lease.state == vim.HttpNfcLease.State.error:
-                raise exception.CoriolisException(lease.error.msg)
-            else:
-                time.sleep(.1)
-
-    def export_instance(self, ctxt, connection_info, instance_name,
-                        export_path):
-        host = connection_info["host"]
-        port = connection_info.get("port", 443)
-        username = connection_info["username"]
-        password = connection_info["password"]
-        allow_untrusted = connection_info.get("allow_untrusted", False)
-
-        # pyVmomi locks otherwise
-        sys.modules['socket'] = eventlet.patcher.original('socket')
-        ssl = eventlet.patcher.original('ssl')
-
-        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
-        if allow_untrusted:
-            context.verify_mode = ssl.CERT_NONE
-
-        self._event_manager.set_total_progress_steps(4)
-
-        self._event_manager.progress_update("Connecting to vSphere host")
-        si = self._connect(host, username, password, port, context)
-        try:
-            self._event_manager.progress_update(
-                "Retrieving virtual machine data")
-            vm_info, vm = self._get_vm_info(si, instance_name)
-            self._event_manager.progress_update("Exporting disks")
-            disk_paths = self._export_disks(vm, export_path, context)
-        finally:
-            connect.Disconnect(si)
-
-        self._event_manager.progress_update("Converting virtual disks format")
-        for disk_path in disk_paths:
-            path = disk_path["path"]
-            LOG.info("Converting VMDK type: %s" % path)
-            tmp_path = "%s.tmp" % path
-            self._convert_disk_type(path, tmp_path)
-            os.remove(path)
-            os.rename(tmp_path, path)
-
-            disks = vm_info["devices"]["disks"]
-            disk_info = [d for d in disks if d["id"] == disk_path["id"]][0]
-            disk_info["path"] = os.path.abspath(path)
-            disk_info["format"] = constants.DISK_FORMAT_VMDK
-
-        return vm_info
+import os
+import sys
+import time
+from urllib import request
+
+import eventlet
+from oslo_config import cfg
+from oslo_log import log as logging
+from pyVim import connect
+from pyVmomi import vim
+
+from coriolis import constants
+from coriolis import exception
+from coriolis.providers import base
+from coriolis.providers.vmware_vsphere import guestid
+from coriolis import utils
+
+vmware_vsphere_opts = [
+    cfg.StrOpt('vdiskmanager_path',
+               default='vmware-vdiskmanager',
+               help='The vmware-vdiskmanager path.'),
+]
+
+CONF = cfg.CONF
+CONF.register_opts(vmware_vsphere_opts, 'vmware_vsphere')
+
+LOG = logging.getLogger(__name__)
+
+
+class ExportProvider(base.BaseExportProvider):
+    def validate_connection_info(self, connection_info):
+        return True
+
+    @utils.retry_on_error()
+    def _convert_disk_type(self, disk_path, target_disk_path, target_type=0):
+        utils.exec_process([CONF.vmware_vsphere.vdiskmanager_path, "-r",
+                            disk_path, "-t", str(target_type),
+                            target_disk_path])
+
+    def _wait_for_task(self, task):
+        while task.info.state not in [vim.TaskInfo.State.success,
+                                      vim.TaskInfo.State.error]:
+            time.sleep(.1)
+        if task.info.state == vim.TaskInfo.State.error:
+            raise exception.CoriolisException(task.info.error.msg)
+
+    @utils.retry_on_error()
+    def _connect(self, host, username, password, port, context):
+        LOG.info("Connecting to: %s:%s" % (host, port))
+        return connect.SmartConnect(
+            host=host,
+            user=username,
+            pwd=password,
+            port=port,
+            sslContext=context)
+
+    def _wait_for_vm_status(self, vm, status, max_wait=120):
+        i = 0
+        while i < max_wait and vm.runtime.powerState != status:
+            time.sleep(1)
+            i += 1
+        return i < max_wait
+
+    @utils.retry_on_error()
+    def _get_vm_info(self, si, instance_name):
+
+        LOG.info("Retrieving data for VM: %s" % instance_name)
+
+        # TODO: provide path selection
+        datacenter = si.content.rootFolder.childEntity[0]
+        vms = datacenter.vmFolder.childEntity
+        vm = [vm for vm in vms if vm.name == instance_name][0]
+
+        firmware_type_map = {
+            vim.vm.GuestOsDescriptor.FirmwareType.bios: 'BIOS',
+            vim.vm.GuestOsDescriptor.FirmwareType.efi: 'EFI'}
+
+        vm_info = {
+            'num_cpu': vm.config.hardware.numCPU,
+            'num_cores_per_socket': vm.config.hardware.numCoresPerSocket,
+            'memory_mb':  vm.config.hardware.memoryMB,
+            'firmware_type':  firmware_type_map[vm.config.firmware],
+            'nested_virtualization': vm.config.nestedHVEnabled,
+            'dynamic_memory_enabled':
+                not vm.config.memoryReservationLockedToMax,
+            'name': vm.config.name,
+            'guest_id': vm.config.guestId,
+            'os_type': guestid.GUEST_ID_OS_TYPE_MAP.get(vm.config.guestId),
+            'id': vm._moId,
+        }
+
+        LOG.info("vm info: %s" % str(vm_info))
+
+        if vm.runtime.powerState != vim.VirtualMachinePowerState.poweredOff:
+            power_off = True
+            if (vm.guest.toolsRunningStatus !=
+                    vim.vm.GuestInfo.ToolsRunningStatus.guestToolsNotRunning):
+                self._event_manager.progress_update("Shutting down guest OS")
+                vm.ShutdownGuest()
+                if self._wait_for_vm_status(
+                        vm, vim.VirtualMachinePowerState.poweredOff):
+                    power_off = False
+
+            if power_off:
+                self._event_manager.progress_update(
+                    "Powering off the virtual machine")
+                task = vm.PowerOff()
+                self._wait_for_task(task)
+
+        disk_ctrls = []
+        devices = [d for d in vm.config.hardware.device if
+                   isinstance(d, vim.vm.device.VirtualController)]
+        for device in devices:
+            ctrl_type = None
+            if isinstance(device, vim.vm.device.VirtualPCIController):
+                ctrl_type = "PCI"
+            elif isinstance(device, vim.vm.device.VirtualSIOController):
+                ctrl_type = "SIO"
+            elif isinstance(device, vim.vm.device.VirtualIDEController):
+                ctrl_type = "IDE"
+            elif isinstance(device, vim.vm.device.VirtualSATAController):
+                ctrl_type = "SATA"
+            elif isinstance(device, vim.vm.device.VirtualSCSIController):
+                ctrl_type = "SCSI"
+            else:
+                continue
+            disk_ctrls.append({'id': device.key, 'type': ctrl_type,
+                               'bus_number': device.busNumber})
+
+        disks = []
+        devices = [d for d in vm.config.hardware.device if
+                   isinstance(d, vim.vm.device.VirtualDisk)]
+        for device in devices:
+            disks.append({'size': device.capacityInBytes,
+                          'address': device.unitNumber,
+                          'id': device.key,
+                          'controller_id': device.controllerKey})
+
+        cdroms = []
+        devices = [d for d in vm.config.hardware.device if
+                   isinstance(d, vim.vm.device.VirtualCdrom)]
+        for device in devices:
+            cdroms.append({'address': device.unitNumber, 'id': device.key,
+                           'controller_id': device.controllerKey})
+
+        floppy = []
+        devices = [d for d in vm.config.hardware.device if
+                   isinstance(d, vim.vm.device.VirtualFloppy)]
+        for device in devices:
+            floppy.append({'address': device.unitNumber, 'id': device.key,
+                           'controller_id': device.controllerKey})
+
+        nics = []
+        devices = [d for d in vm.config.hardware.device if
+                   isinstance(d, vim.vm.device.VirtualEthernetCard)]
+        for device in devices:
+            nics.append({'mac_address': device.macAddress, 'id': device.key,
+                         'name': device.deviceInfo.label,
+                         'network_name': device.backing.network.name})
+
+        serial_ports = []
+        devices = [d for d in vm.config.hardware.device if
+                   isinstance(d, vim.vm.device.VirtualSerialPort)]
+        for device in devices:
+            serial_ports.append({'id': device.key})
+
+        boot_order = []
+        for boot_device in vm.config.bootOptions.bootOrder:
+            if isinstance(boot_device, vim.vm.BootOptions.BootableDiskDevice):
+                boot_order.append({"type": "disk",
+                                   "id": boot_device.deviceKey})
+            elif isinstance(boot_device,
+                            vim.vm.BootOptions.BootableCdromDevice):
+                boot_order.append({"type": "cdrom", "id": None})
+            elif isinstance.append(boot_device,
+                                   vim.vm.BootOptions.BootableEthernetDevice):
+                boot_order.append({"type": "ethernet",
+                                   "id": boot_device.deviceKey})
+            elif isinstance(boot_device,
+                            vim.vm.BootOptions.BootableFloppyDevice):
+                boot_order.append({"type": "floppy", "id": None})
+
+        vm_info["devices"] = {
+            "nics": nics,
+            "controllers": disk_ctrls,
+            "disks": disks,
+            "cdroms": cdroms,
+            "floppy": floppy,
+        }
+        vm_info["boot_order"] = boot_order
+
+        return vm_info, vm
+
+    @utils.retry_on_error()
+    def _export_disks(self, vm, export_path, context):
+        disk_paths = []
+        lease = vm.ExportVm()
+        while True:
+            if lease.state == vim.HttpNfcLease.State.ready:
+                try:
+                    tot_downloaded_bytes = 0
+                    for du in [du for du in lease.info.deviceUrl if du.disk]:
+                        # Key format: '/vm-70/VirtualLsiLogicController0:0'
+                        ctrl_str, address = du.key[
+                            du.key.rindex('/') + 1:].split(':')
+
+                        def _get_class_name(obj):
+                            return obj.__class__.__name__.split('.')[-1]
+
+                        for i, ctrl in enumerate(
+                            [d for d in vm.config.hardware.device if
+                             isinstance(
+                                d, vim.vm.device.VirtualController) and
+                                ctrl_str.startswith(_get_class_name(d))]):
+                            if int(ctrl_str[len(_get_class_name(ctrl)):]) == i:
+                                disk_key = [
+                                    d for d in vm.config.hardware.device if
+                                    isinstance(
+                                        d, vim.vm.device.VirtualDisk) and
+                                    d.controllerKey == ctrl.key and
+                                    d.unitNumber == int(address)][0].key
+                                break
+
+                        response = request.urlopen(du.url, context=context)
+                        path = os.path.join(export_path, du.targetId)
+                        disk_paths.append({'path': path, 'id': disk_key})
+
+                        LOG.info("Downloading: %s" % path)
+                        with open(path, 'wb') as f:
+                            while True:
+                                chunk = response.read(1024 * 1024)
+                                if not chunk:
+                                    break
+                                tot_downloaded_bytes += len(chunk)
+                                f.write(chunk)
+                                lease.HttpNfcLeaseProgress(
+                                    int(tot_downloaded_bytes * 100 /
+                                        (lease.info.totalDiskCapacityInKB *
+                                         1024)))
+
+                    lease.HttpNfcLeaseComplete()
+                    return disk_paths
+                except:
+                    lease.HttpNfcLeaseAbort()
+                    raise
+            elif lease.state == vim.HttpNfcLease.State.error:
+                raise exception.CoriolisException(lease.error.msg)
+            else:
+                time.sleep(.1)
+
+    def export_instance(self, ctxt, connection_info, instance_name,
+                        export_path):
+        host = connection_info["host"]
+        port = connection_info.get("port", 443)
+        username = connection_info["username"]
+        password = connection_info["password"]
+        allow_untrusted = connection_info.get("allow_untrusted", False)
+
+        # pyVmomi locks otherwise
+        sys.modules['socket'] = eventlet.patcher.original('socket')
+        ssl = eventlet.patcher.original('ssl')
+
+        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+        if allow_untrusted:
+            context.verify_mode = ssl.CERT_NONE
+
+        self._event_manager.set_total_progress_steps(4)
+
+        self._event_manager.progress_update("Connecting to vSphere host")
+        si = self._connect(host, username, password, port, context)
+        try:
+            self._event_manager.progress_update(
+                "Retrieving virtual machine data")
+            vm_info, vm = self._get_vm_info(si, instance_name)
+            self._event_manager.progress_update("Exporting disks")
+            disk_paths = self._export_disks(vm, export_path, context)
+        finally:
+            connect.Disconnect(si)
+
+        self._event_manager.progress_update("Converting virtual disks format")
+        for disk_path in disk_paths:
+            path = disk_path["path"]
+            LOG.info("Converting VMDK type: %s" % path)
+            tmp_path = "%s.tmp" % path
+            self._convert_disk_type(path, tmp_path)
+            os.remove(path)
+            os.rename(tmp_path, path)
+
+            disks = vm_info["devices"]["disks"]
+            disk_info = [d for d in disks if d["id"] == disk_path["id"]][0]
+            disk_info["path"] = os.path.abspath(path)
+            disk_info["format"] = constants.DISK_FORMAT_VMDK
+
+        return vm_info

+ 245 - 245
coriolis/providers/vmware_vsphere/guestid.py

@@ -1,245 +1,245 @@
-from pyVmomi import vim
-
-from coriolis import constants
-
-
-GUEST_ID_OS_TYPE_MAP = {
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetStandard64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win95Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.centosGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other24xLinux64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.fedoraGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux3Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.slesGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin11Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin13_64Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win31Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel3Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.openServer6Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winVista64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows7Server64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris6Guest:
-    constants.OS_TYPE_SOLARIS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel7Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris7Guest:
-    constants.OS_TYPE_SOLARIS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian6_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian7_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winLonghorn64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin11_64Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.mandrakeGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winVistaGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows7Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles10_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows7_64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris10_64Guest:
-    constants.OS_TYPE_SOLARIS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNTGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles12_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetDatacenter64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win98Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetWebGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.genericLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin10_64Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.netware6Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian7Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.freebsd64Guest:
-    constants.OS_TYPE_BSD,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris10Guest:
-    constants.OS_TYPE_SOLARIS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other24xLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows8Server64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.fedora64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian6Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win2000AdvServGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.nld9Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux4_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel7_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin12_64Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles10Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwinGuest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris8Guest:
-    constants.OS_TYPE_SOLARIS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win2000ProGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winMeGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.eComStation2Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetStandardGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.mandrivaGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.opensuse64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.suseGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows8_64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windowsHyperVGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel2Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel5Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other3xLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.netware4Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other26xLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.opensuseGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winXPHomeGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.openServer5Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winLonghornGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles11_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel4Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel6_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian5_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles12Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris11_64Guest:
-    constants.OS_TYPE_SOLARIS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.oesGuest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.turboLinux64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.centos64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.oracleLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.os2Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian4Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherGuest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles11Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows8Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.netware5Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other3xLinux64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.mandriva64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other26xLinux64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.ubuntuGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetDatacenterGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherGuest64:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.suse64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.redhatGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.vmkernelGuest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winXPPro64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.unixWare7Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherLinux64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.turboLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.dosGuest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherLinuxGuest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin10Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian5Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win2000ServGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel4_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel5_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian4_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.ubuntu64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux4Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetEnterprise64Guest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin64Guest:
-    constants.OS_TYPE_OS_X,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sjdsGuest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel6Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.freebsdGuest:
-    constants.OS_TYPE_BSD,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.eComStationGuest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux3_64Guest:
-    constants.OS_TYPE_LINUX,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetEnterpriseGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winXPProGuest:
-    constants.OS_TYPE_WINDOWS,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.vmkernel5Guest:
-    None,
-    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris9Guest:
-    constants.OS_TYPE_SOLARIS,
-}
+from pyVmomi import vim
+
+from coriolis import constants
+
+
+GUEST_ID_OS_TYPE_MAP = {
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetStandard64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win95Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.centosGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other24xLinux64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.fedoraGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux3Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.slesGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin11Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin13_64Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win31Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel3Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.openServer6Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winVista64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows7Server64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris6Guest:
+    constants.OS_TYPE_SOLARIS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel7Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris7Guest:
+    constants.OS_TYPE_SOLARIS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian6_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian7_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winLonghorn64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin11_64Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.mandrakeGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winVistaGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows7Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles10_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows7_64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris10_64Guest:
+    constants.OS_TYPE_SOLARIS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNTGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles12_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetDatacenter64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win98Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetWebGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.genericLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin10_64Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.netware6Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian7Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.freebsd64Guest:
+    constants.OS_TYPE_BSD,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris10Guest:
+    constants.OS_TYPE_SOLARIS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other24xLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows8Server64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.fedora64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian6Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win2000AdvServGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.nld9Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux4_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel7_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin12_64Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles10Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwinGuest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris8Guest:
+    constants.OS_TYPE_SOLARIS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win2000ProGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winMeGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.eComStation2Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetStandardGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.mandrivaGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.opensuse64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.suseGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows8_64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windowsHyperVGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel2Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel5Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other3xLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.netware4Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other26xLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.opensuseGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winXPHomeGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.openServer5Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winLonghornGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles11_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel4Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel6_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian5_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles12Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris11_64Guest:
+    constants.OS_TYPE_SOLARIS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.oesGuest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.turboLinux64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.centos64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.oracleLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.os2Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian4Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherGuest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles11Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.windows8Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.netware5Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other3xLinux64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.mandriva64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.other26xLinux64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.ubuntuGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetDatacenterGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherGuest64:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.suse64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.redhatGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.vmkernelGuest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winXPPro64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.unixWare7Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherLinux64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.turboLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.dosGuest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.otherLinuxGuest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin10Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian5Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.win2000ServGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel4_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel5_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.debian4_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.ubuntu64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux4Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetEnterprise64Guest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.darwin64Guest:
+    constants.OS_TYPE_OS_X,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sjdsGuest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.rhel6Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.freebsdGuest:
+    constants.OS_TYPE_BSD,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.eComStationGuest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.sles64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.asianux3_64Guest:
+    constants.OS_TYPE_LINUX,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winNetEnterpriseGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.winXPProGuest:
+    constants.OS_TYPE_WINDOWS,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.vmkernel5Guest:
+    None,
+    vim.vm.GuestOsDescriptor.GuestOsIdentifier.solaris9Guest:
+    constants.OS_TYPE_SOLARIS,
+}

+ 57 - 57
coriolis/rpc.py

@@ -1,57 +1,57 @@
-from oslo_config import cfg
-import oslo_messaging as messaging
-
-from coriolis import context
-import coriolis.exception
-
-rpc_opts = [
-    cfg.StrOpt('messaging_transport_url',
-               default="rabbit://guest:guest@127.0.0.1:5672/",
-               help='Messaging transport url'),
-]
-
-CONF = cfg.CONF
-CONF.register_opts(rpc_opts)
-
-ALLOWED_EXMODS = [
-    coriolis.exception.__name__,
-]
-
-
-class RequestContextSerializer(messaging.Serializer):
-
-    def __init__(self, base):
-        self._base = base
-
-    def serialize_entity(self, ctxt, entity):
-        if not self._base:
-            return entity
-        return self._base.serialize_entity(ctxt, entity)
-
-    def deserialize_entity(self, ctxt, entity):
-        if not self._base:
-            return entity
-        return self._base.deserialize_entity(ctxt, entity)
-
-    def serialize_context(self, ctxt):
-        return ctxt.to_dict()
-
-    def deserialize_context(self, ctxt):
-        return context.RequestContext.from_dict(ctxt)
-
-
-def _get_transport():
-    return messaging.get_transport(cfg.CONF, CONF.messaging_transport_url,
-                                   allowed_remote_exmods=ALLOWED_EXMODS)
-
-
-def get_client(target, serializer=None):
-    serializer = RequestContextSerializer(serializer)
-    return messaging.RPCClient(_get_transport(), target, serializer=serializer)
-
-
-def get_server(target, endpoints, serializer=None):
-    serializer = RequestContextSerializer(serializer)
-    return messaging.get_rpc_server(_get_transport(), target, endpoints,
-                                    executor='eventlet',
-                                    serializer=serializer)
+from oslo_config import cfg
+import oslo_messaging as messaging
+
+from coriolis import context
+import coriolis.exception
+
+rpc_opts = [
+    cfg.StrOpt('messaging_transport_url',
+               default="rabbit://guest:guest@127.0.0.1:5672/",
+               help='Messaging transport url'),
+]
+
+CONF = cfg.CONF
+CONF.register_opts(rpc_opts)
+
+ALLOWED_EXMODS = [
+    coriolis.exception.__name__,
+]
+
+
+class RequestContextSerializer(messaging.Serializer):
+
+    def __init__(self, base):
+        self._base = base
+
+    def serialize_entity(self, ctxt, entity):
+        if not self._base:
+            return entity
+        return self._base.serialize_entity(ctxt, entity)
+
+    def deserialize_entity(self, ctxt, entity):
+        if not self._base:
+            return entity
+        return self._base.deserialize_entity(ctxt, entity)
+
+    def serialize_context(self, ctxt):
+        return ctxt.to_dict()
+
+    def deserialize_context(self, ctxt):
+        return context.RequestContext.from_dict(ctxt)
+
+
+def _get_transport():
+    return messaging.get_transport(cfg.CONF, CONF.messaging_transport_url,
+                                   allowed_remote_exmods=ALLOWED_EXMODS)
+
+
+def get_client(target, serializer=None):
+    serializer = RequestContextSerializer(serializer)
+    return messaging.RPCClient(_get_transport(), target, serializer=serializer)
+
+
+def get_server(target, endpoints, serializer=None):
+    serializer = RequestContextSerializer(serializer)
+    return messaging.get_rpc_server(_get_transport(), target, endpoints,
+                                    executor='eventlet',
+                                    serializer=serializer)

+ 11 - 11
coriolis/secrets.py

@@ -1,11 +1,11 @@
-import json
-
-from barbicanclient import client as barbican_client
-
-from coriolis import keystone
-
-
-def get_secret(ctxt, secret_ref):
-    session = keystone.create_keystone_session(ctxt)
-    barbican = barbican_client.Client(session=session)
-    return json.loads(barbican.secrets.get(secret_ref).payload)
+import json
+
+from barbicanclient import client as barbican_client
+
+from coriolis import keystone
+
+
+def get_secret(ctxt, secret_ref):
+    session = keystone.create_keystone_session(ctxt)
+    barbican = barbican_client.Client(session=session)
+    return json.loads(barbican.secrets.get(secret_ref).payload)

+ 114 - 114
coriolis/wsman.py

@@ -1,114 +1,114 @@
-import base64
-
-from oslo_log import log as logging
-from winrm import protocol
-
-from coriolis import exception
-from coriolis import utils
-
-AUTH_BASIC = "basic"
-AUTH_KERBEROS = "kerberos"
-AUTH_CERTIFICATE = "certificate"
-
-CODEPAGE_UTF8 = 65001
-
-LOG = logging.getLogger(__name__)
-
-
-class WSManConnection(object):
-    def __init__(self):
-        self._protocol = None
-
-    EOL = "\r\n"
-
-    @utils.retry_on_error()
-    def connect(self, url, username, auth=None, password=None,
-                cert_pem=None, cert_key_pem=None):
-        protocol.Protocol.DEFAULT_TIMEOUT = 3600
-
-        if not auth:
-            if cert_pem:
-                auth = AUTH_CERTIFICATE
-            else:
-                auth = AUTH_BASIC
-
-        auth_transport_map = {AUTH_BASIC: 'plaintext',
-                              AUTH_KERBEROS: 'kerberos',
-                              AUTH_CERTIFICATE: 'ssl'}
-
-        self._protocol = protocol.Protocol(
-            endpoint=url,
-            transport=auth_transport_map[auth],
-            username=username,
-            password=password,
-            cert_pem=cert_pem,
-            cert_key_pem=cert_key_pem)
-
-    def disconnect(self):
-        self._protocol = None
-
-    @utils.retry_on_error()
-    def _exec_command(self, cmd, args=[]):
-        shell_id = self._protocol.open_shell(codepage=CODEPAGE_UTF8)
-        try:
-            command_id = self._protocol.run_command(shell_id, cmd, args)
-            try:
-                (std_out,
-                 std_err,
-                 exit_code) = self._protocol.get_command_output(
-                    shell_id, command_id)
-            finally:
-                self._protocol.cleanup_command(shell_id, command_id)
-
-            return (std_out, std_err, exit_code)
-        finally:
-            self._protocol.close_shell(shell_id)
-
-    def exec_command(self, cmd, args=[]):
-        LOG.debug("Executing WSMAN command: %s", str([cmd] + args))
-        std_out, std_err, exit_code = self._exec_command(cmd, args)
-
-        if exit_code:
-            raise exception.CoriolisException(
-                "Command \"%s\" failed with exit code: %s\n"
-                "stdout: %s\nstd_err: %s" %
-                (str([cmd] + args), exit_code, std_out, std_err))
-
-        return std_out
-
-    def exec_ps_command(self, cmd, ignore_stdout=False):
-        # This is needed to avoid Nano Server's output formatting
-        if not ignore_stdout:
-            cmd_fmt = "\"%s | out-file out.txt\""
-        else:
-            cmd_fmt = "\"%s\""
-
-        self.exec_command("powershell.exe", [cmd_fmt % cmd])
-
-        if not ignore_stdout:
-            return self.exec_command("cmd.exe", ["/c", "type", "out.txt"])[:-2]
-
-    def test_path(self, remote_path):
-        ret_val = self.exec_ps_command("Test-Path -Path \"%s\"" % remote_path)
-        return ret_val == "True"
-
-    def download_file(self, url, remote_path):
-        LOG.debug("Downloading: \"%(url)s\" to \"%(path)s\"",
-                  {"url": url, "path": remote_path})
-        # Nano Server does not have Invoke-WebRequest and additionally
-        # this is also faster
-        self.exec_ps_command(
-            "if(!([System.Management.Automation.PSTypeName]'"
-            "System.Net.Http.HttpClient').Type) {$assembly = "
-            "[System.Reflection.Assembly]::LoadWithPartialName("
-            "'System.Net.Http')}; (new-object System.Net.Http.HttpClient)."
-            "GetStreamAsync('%(url)s').Result.CopyTo("
-            "(New-Object IO.FileStream '%(outfile)s', Create, Write, None), "
-            "1MB)" % {"url": url, "outfile": remote_path},
-            ignore_stdout=True)
-
-    def write_file(self, remote_path, content):
-        self.exec_ps_command(
-            "[IO.File]::WriteAllBytes('%s', [Convert]::FromBase64String('%s'))"
-            % (remote_path, base64.b64encode(content).decode()),
-            ignore_stdout=True)
+import base64
+
+from oslo_log import log as logging
+from winrm import protocol
+
+from coriolis import exception
+from coriolis import utils
+
+AUTH_BASIC = "basic"
+AUTH_KERBEROS = "kerberos"
+AUTH_CERTIFICATE = "certificate"
+
+CODEPAGE_UTF8 = 65001
+
+LOG = logging.getLogger(__name__)
+
+
+class WSManConnection(object):
+    def __init__(self):
+        self._protocol = None
+
+    EOL = "\r\n"
+
+    @utils.retry_on_error()
+    def connect(self, url, username, auth=None, password=None,
+                cert_pem=None, cert_key_pem=None):
+        protocol.Protocol.DEFAULT_TIMEOUT = 3600
+
+        if not auth:
+            if cert_pem:
+                auth = AUTH_CERTIFICATE
+            else:
+                auth = AUTH_BASIC
+
+        auth_transport_map = {AUTH_BASIC: 'plaintext',
+                              AUTH_KERBEROS: 'kerberos',
+                              AUTH_CERTIFICATE: 'ssl'}
+
+        self._protocol = protocol.Protocol(
+            endpoint=url,
+            transport=auth_transport_map[auth],
+            username=username,
+            password=password,
+            cert_pem=cert_pem,
+            cert_key_pem=cert_key_pem)
+
+    def disconnect(self):
+        self._protocol = None
+
+    @utils.retry_on_error()
+    def _exec_command(self, cmd, args=[]):
+        shell_id = self._protocol.open_shell(codepage=CODEPAGE_UTF8)
+        try:
+            command_id = self._protocol.run_command(shell_id, cmd, args)
+            try:
+                (std_out,
+                 std_err,
+                 exit_code) = self._protocol.get_command_output(
+                    shell_id, command_id)
+            finally:
+                self._protocol.cleanup_command(shell_id, command_id)
+
+            return (std_out, std_err, exit_code)
+        finally:
+            self._protocol.close_shell(shell_id)
+
+    def exec_command(self, cmd, args=[]):
+        LOG.debug("Executing WSMAN command: %s", str([cmd] + args))
+        std_out, std_err, exit_code = self._exec_command(cmd, args)
+
+        if exit_code:
+            raise exception.CoriolisException(
+                "Command \"%s\" failed with exit code: %s\n"
+                "stdout: %s\nstd_err: %s" %
+                (str([cmd] + args), exit_code, std_out, std_err))
+
+        return std_out
+
+    def exec_ps_command(self, cmd, ignore_stdout=False):
+        # This is needed to avoid Nano Server's output formatting
+        if not ignore_stdout:
+            cmd_fmt = "\"%s | out-file out.txt\""
+        else:
+            cmd_fmt = "\"%s\""
+
+        self.exec_command("powershell.exe", [cmd_fmt % cmd])
+
+        if not ignore_stdout:
+            return self.exec_command("cmd.exe", ["/c", "type", "out.txt"])[:-2]
+
+    def test_path(self, remote_path):
+        ret_val = self.exec_ps_command("Test-Path -Path \"%s\"" % remote_path)
+        return ret_val == "True"
+
+    def download_file(self, url, remote_path):
+        LOG.debug("Downloading: \"%(url)s\" to \"%(path)s\"",
+                  {"url": url, "path": remote_path})
+        # Nano Server does not have Invoke-WebRequest and additionally
+        # this is also faster
+        self.exec_ps_command(
+            "if(!([System.Management.Automation.PSTypeName]'"
+            "System.Net.Http.HttpClient').Type) {$assembly = "
+            "[System.Reflection.Assembly]::LoadWithPartialName("
+            "'System.Net.Http')}; (new-object System.Net.Http.HttpClient)."
+            "GetStreamAsync('%(url)s').Result.CopyTo("
+            "(New-Object IO.FileStream '%(outfile)s', Create, Write, None), "
+            "1MB)" % {"url": url, "outfile": remote_path},
+            ignore_stdout=True)
+
+    def write_file(self, remote_path, content):
+        self.exec_ps_command(
+            "[IO.File]::WriteAllBytes('%s', [Convert]::FromBase64String('%s'))"
+            % (remote_path, base64.b64encode(content).decode()),
+            ignore_stdout=True)