Ejemplo n.º 1
0
    def initGui(self):
        """
        Loads required values inside
        """

        # Here we have to use "default values", cause values aren't used at form initialization
        # This is that value is always '', so if we want to change something, we have to do it
        # at defValue

        machines = self.parent().getMachines()
        storages = self.parent().getStorages()
        networks = self.parent().getNetworks()
        machines_list = []
        for m in machines:
            machines_list.append(gui.choiceItem(m['id'], m['name']))
        storages_list = []
        for storage in storages:
            space, free = storage['size'] / 1024, (storage['size'] -
                                                   storage['used']) / 1024
            storages_list.append(
                gui.choiceItem(
                    storage['id'],
                    "%s (%4.2f Gb/%4.2f Gb)" % (storage['name'], space, free)))
        network_list = []
        for net in networks:
            network_list.append(gui.choiceItem(net['id'], net['name']))

        self.machine.setValues(machines_list)
        self.datastore.setValues(storages_list)
        self.network.setValues(network_list)
Ejemplo n.º 2
0
    def initGui(self):
        '''
        Loads required values inside
        '''

        # Here we have to use "default values", cause values aren't used at form initialization
        # This is that value is always '', so if we want to change something, we have to do it
        # at defValue
        self.ov.defValue = self.parent().serialize()
        self.ev.defValue = self.parent().env().key()

        machines = self.parent().getMachines()
        vals = []
        for m in machines:
            vals.append(gui.choiceItem(m['id'], m['name']))

        # This is not the same case, values is not the "value" of the field, but
        # the list of values shown because this is a "ChoiceField"
        self.machine.setValues(vals)

        clusters = self.parent().getClusters()
        vals = []
        for c in clusters:
            vals.append(gui.choiceItem(c['id'], c['name']))
        self.cluster.setValues(vals)
Ejemplo n.º 3
0
 def initGui(self):
     logger.debug('Initializing gui')
     vals = [gui.choiceItem('0-0-0-0', ugettext('ALL POOLS'))] + [
         gui.choiceItem(v.uuid, v.name)
         for v in ServicePool.objects.all().order_by('name')
     ]
     self.pool.setValues(vals)
Ejemplo n.º 4
0
    def initGui(self):
        '''
        Loads required values inside
        '''

        # Here we have to use "default values", cause values aren't used at form initialization
        # This is that value is always '', so if we want to change something, we have to do it
        # at defValue
        self.ov.defValue = self.parent().serialize()
        self.ev.defValue = self.parent().env().key()

        machines = self.parent().getMachines()
        vals = []
        for m in machines:
            vals.append(gui.choiceItem(m['id'], m['name']))

        # This is not the same case, values is not the "value" of the field, but
        # the list of values shown because this is a "ChoiceField"
        self.machine.setValues(vals)

        clusters = self.parent().getClusters()
        vals = []
        for c in clusters:
            vals.append(gui.choiceItem(c['id'], c['name']))
        self.cluster.setValues(vals)
Ejemplo n.º 5
0
    def initGui(self):
        """
        Loads required values inside
        """

        # Here we have to use "default values", cause values aren't used at form initialization
        # This is that value is always '', so if we want to change something, we have to do it
        # at defValue

        machines = self.parent().getMachines()
        storages = self.parent().getStorages()
        networks = self.parent().getNetworks()
        machines_list = []
        for m in machines:
            machines_list.append(gui.choiceItem(m['id'], m['name']))
        storages_list = []
        for storage in storages:
            space, free = storage['size'] / 1024, (storage['size'] - storage['used']) / 1024
            storages_list.append(gui.choiceItem(storage['id'], "%s (%4.2f Gb/%4.2f Gb)" % (storage['name'], space, free)))
        network_list = []
        for net in networks:
            network_list.append(gui.choiceItem(net['id'], net['name']))

        self.machine.setValues(machines_list)
        self.datastore.setValues(storages_list)
        self.network.setValues(network_list)
Ejemplo n.º 6
0
def getResources(parameters):
    '''
    This helper is designed as a callback for Project Selector
    '''
    from .Provider import OGProvider
    from uds.core.Environment import Environment
    logger.debug(
        'Parameters received by getResources Helper: {0}'.format(parameters))
    env = Environment(parameters['ev'])
    provider = OGProvider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api

    labs = [gui.choiceItem('0', _('All Labs'))] + [
        gui.choiceItem(l['id'], l['name'])
        for l in api.getLabs(ou=parameters['ou'])
    ]
    images = [
        gui.choiceItem(z['id'], z['name'])
        for z in api.getImages(ou=parameters['ou'])
    ]

    data = [
        {
            'name': 'lab',
            'values': labs
        },
        {
            'name': 'image',
            'values': images
        },
    ]
    logger.debug('Return data: {}'.format(data))
    return data
Ejemplo n.º 7
0
def getResources(
        parameters: typing.Any) -> typing.List[typing.Dict[str, typing.Any]]:
    from .provider import OGProvider

    logger.debug('Parameters received by getResources Helper: %s', parameters)
    env = Environment(parameters['ev'])
    provider = OGProvider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api

    labs = [gui.choiceItem('0', _('All Labs'))] + [
        gui.choiceItem(l['id'], l['name'])
        for l in api.getLabs(ou=parameters['ou'])
    ]
    images = [
        gui.choiceItem(z['id'], z['name'])
        for z in api.getImages(ou=parameters['ou'])
    ]

    data = [
        {
            'name': 'lab',
            'values': labs
        },
        {
            'name': 'image',
            'values': images
        },
    ]
    logger.debug('Return data: %s', data)

    return data
Ejemplo n.º 8
0
    def initGui(self):
        """
        Loads required values inside
        """
        api = self.parent().api()

        if not self.parent().legacy and self.parent().region.value:
            regions = [
                gui.choiceItem(self.parent().region.value,
                               self.parent().region.value)
            ]
        else:
            regions = [
                gui.choiceItem(r['id'], r['id']) for r in api.listRegions()
            ]

        self.region.setValues(regions)

        if not self.parent().legacy and self.parent().tenant.value:
            tenants = [
                gui.choiceItem(self.parent().tenant.value,
                               self.parent().tenant.value)
            ]
        else:
            tenants = [
                gui.choiceItem(t['id'], t['name']) for t in api.listProjects()
            ]
        self.project.setValues(tenants)

        # So we can instantiate parent to get API
        logger.debug(self.parent().serialize())

        self.ov.setDefValue(self.parent().serialize())
        self.ev.setDefValue(self.parent().env.key)
        self.legacy.setDefValue(self.parent().legacy and 'true' or 'false')
Ejemplo n.º 9
0
    def getGui(self, parent: 'Provider',
               forType: str) -> typing.Iterable[typing.Any]:
        try:
            logger.debug('getGui parameters: %s, %s', parent, forType)
            parentInstance = parent.getInstance()
            serviceType = parentInstance.getServiceByType(forType)
            if not serviceType:
                raise self.invalidItemException(
                    'Gui for {} not found'.format(forType))

            service = serviceType(
                Environment.getTempEnv(), parentInstance
            )  # Instantiate it so it has the opportunity to alter gui description based on parent
            localGui = self.addDefaultFields(service.guiDescription(service),
                                             ['name', 'comments', 'tags'])
            if GlobalConfig.EXPERIMENTAL_FEATURES.getBool():
                self.addField(
                    localGui,
                    {
                        'name':
                        'proxy_id',
                        'values':
                        [gui.choiceItem(-1, '')] + gui.sortedChoices([
                            gui.choiceItem(v.uuid, v.name)
                            for v in models.Proxy.objects.all()
                        ]),
                        'label':
                        _('Proxy'),
                        'tooltip':
                        _('Proxy for services behind a firewall'),
                        'type':
                        gui.InputField.CHOICE_TYPE,
                        'tab':
                        _('Advanced'),
                        'order':
                        132,
                    },
                )
            else:
                self.addField(
                    localGui,
                    {
                        'name': 'proxy_id',
                        'value': '-1',
                        'type': gui.InputField.HIDDEN_TYPE,
                    },
                )

            return localGui

        except Exception as e:
            logger.exception('getGui')
            raise ResponseError(str(e))
Ejemplo n.º 10
0
    def initGui(self) -> None:
        """
        Loads required values inside
        """

        t: 'on.types.TemplateType'
        self.template.setValues([
            gui.choiceItem(t.id, t.name) for t in self.parent().getTemplates()
        ])

        d: 'on.types.StorageType'
        self.datastore.setValues([
            gui.choiceItem(d.id, d.name)
            for d in self.parent().getDatastores()
        ])
Ejemplo n.º 11
0
def getVolumes(parameters):
    """
    This helper is designed as a callback for Zone Selector
    """
    from .Provider import Provider
    from uds.core.Environment import Environment
    logger.debug(
        'Parameters received by getVolumes Helper: {0}'.format(parameters))
    env = Environment(parameters['ev'])
    provider = Provider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api(parameters['project'], parameters['region'])

    volumes = [
        gui.choiceItem(v['id'], v['name']) for v in api.listVolumes()
        if v['name'] != ''
        and v['availability_zone'] == parameters['availabilityZone']
    ]

    data = [
        {
            'name': 'volume',
            'values': volumes
        },
    ]
    logger.debug('Return data: {}'.format(data))
    return data
Ejemplo n.º 12
0
    def initGui(self):
        '''
        Loads required values inside
        '''
        api = self.parent().api()
        regions = [gui.choiceItem(r['id'], r['id']) for r in api.listRegions()]
        self.region.setValues(regions)

        tenants = [gui.choiceItem(t['id'], t['name']) for t in api.listProjects()]
        self.project.setValues(tenants)

        # So we can instantiate parent to get API
        logger.debug(self.parent().serialize())

        self.ov.setDefValue(self.parent().serialize())
        self.ev.setDefValue(self.parent().env.key)
Ejemplo n.º 13
0
 def initGui(self):
     logger.debug('Initializing gui')
     vals = [
         gui.choiceItem(v.uuid, v.name)
         for v in ServicePool.objects.all().order_by('name')
     ]
     self.pools.setValues(vals)
Ejemplo n.º 14
0
    def initGui(self):
        logger.debug('Initializing gui')
        vals = [
            gui.choiceItem(v.uuid, v.name)
            for v in Authenticator.objects.all()
        ]

        self.authenticator.setValues(vals)
Ejemplo n.º 15
0
    def initGui(self):
        """
        Loads required values inside
        """
        api = self.parent().api()
        regions = [gui.choiceItem(r['id'], r['id']) for r in api.listRegions()]
        self.region.setValues(regions)

        tenants = [
            gui.choiceItem(t['id'], t['name']) for t in api.listProjects()
        ]
        self.project.setValues(tenants)

        # So we can instantiate parent to get API
        logger.debug(self.parent().serialize())

        self.ov.setDefValue(self.parent().serialize())
        self.ev.setDefValue(self.parent().env.key)
Ejemplo n.º 16
0
    def initGui(self):
        """
        Loads required values inside
        """
        ous = [gui.choiceItem(r['id'], r['name']) for r in self.parent().api.getOus()]
        self.ou.setValues(ous)

        self.ov.setDefValue(self.parent().serialize())
        self.ev.setDefValue(self.parent().env.key)
Ejemplo n.º 17
0
    def initGui(self):
        '''
        Loads required values inside
        '''
        ous = [gui.choiceItem(r['id'], r['name']) for r in self.parent().api.getOus()]
        self.ou.setValues(ous)

        self.ov.setDefValue(self.parent().serialize())
        self.ev.setDefValue(self.parent().env.key)
Ejemplo n.º 18
0
    def initGui(self):
        """
        Loads required values inside
        """

        templates = self.parent().getTemplates()
        vals = []
        for t in templates:
            vals.append(gui.choiceItem(t[0], t[1]))

        # This is not the same case, values is not the "value" of the field, but
        # the list of values shown because this is a "ChoiceField"
        self.template.setValues(vals)

        datastores = self.parent().getDatastores()
        vals = []
        for d in datastores:
            vals.append(gui.choiceItem(d[0], d[1]))

        self.datastore.setValues(vals)
Ejemplo n.º 19
0
    def initGui(self):
        '''
        Loads required values inside
        '''

        templates = self.parent().getTemplates()
        vals = []
        for t in templates:
            vals.append(gui.choiceItem(t[0], t[1]))

        # This is not the same case, values is not the "value" of the field, but
        # the list of values shown because this is a "ChoiceField"
        self.template.setValues(vals)

        datastores = self.parent().getDatastores()
        vals = []
        for d in datastores:
            vals.append(gui.choiceItem(d[0], d[1]))

        self.datastore.setValues(vals)
Ejemplo n.º 20
0
    def initGui(self) -> None:
        # Here we have to use "default values", cause values aren't used at form initialization
        # This is that value is always '', so if we want to change something, we have to do it
        # at defValue
        self.ov.defValue = self.parent().serialize()
        self.ev.defValue = self.parent().env.key

        # This is not the same case, values is not the "value" of the field, but
        # the list of values shown because this is a "ChoiceField"
        self.machine.setValues([
            gui.choiceItem(str(m.vmid), '{}\{}'.format(m.node, m.name
                                                       or m.vmid))
            for m in self.parent().listMachines()
            if m.name and m.name[:3] != 'UDS'
        ])
        self.pool.setValues([gui.choiceItem('', _('None'))] + [
            gui.choiceItem(p.poolid, p.poolid)
            for p in self.parent().listPools()
        ])
        self.ha.setValues([
            gui.choiceItem('', _('Enabled')),
            gui.choiceItem('__', _('Disabled'))
        ] + [
            gui.choiceItem(group, group)
            for group in self.parent().listHaGroups()
        ])
Ejemplo n.º 21
0
def getResources(parameters):
    """
    This helper is designed as a callback for Project Selector
    """
    from .Provider import Provider
    from uds.core.Environment import Environment
    logger.debug('Parameters received by getResources Helper: {0}'.format(parameters))
    env = Environment(parameters['ev'])
    provider = Provider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api(parameters['project'], parameters['region'])

    zones = [gui.choiceItem(z, z) for z in api.listAvailabilityZones()]
    networks = [gui.choiceItem(z['id'], z['name']) for z in api.listNetworks()]
    flavors = [gui.choiceItem(z['id'], z['name']) for z in api.listFlavors()]
    securityGroups = [gui.choiceItem(z['id'], z['name']) for z in api.listSecurityGroups()]
    volumeTypes = [gui.choiceItem('-', _('None'))] + [gui.choiceItem(t['id'], t['name']) for t in api.listVolumeTypes()]

    data = [
        {'name': 'availabilityZone', 'values': zones },
        {'name': 'network', 'values': networks },
        {'name': 'flavor', 'values': flavors },
        {'name': 'securityGroups', 'values': securityGroups },
        {'name': 'volumeType', 'values': volumeTypes },
    ]
    logger.debug('Return data: {}'.format(data))
    return data
Ejemplo n.º 22
0
def getResources(parameters):
    '''
    This helper is designed as a callback for Project Selector
    '''
    if parameters['legacy'] == 'true':
        from .ProviderLegacy import ProviderLegacy as Provider
    else:
        from .Provider import Provider
    from uds.core.Environment import Environment
    logger.debug('Parameters received by getResources Helper: {0}'.format(parameters))
    env = Environment(parameters['ev'])
    provider = Provider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api(parameters['project'], parameters['region'])

    zones = [gui.choiceItem(z, z) for z in api.listAvailabilityZones()]
    networks = [gui.choiceItem(z['id'], z['name']) for z in api.listNetworks()]
    flavors = [gui.choiceItem(z['id'], z['name']) for z in api.listFlavors()]
    securityGroups = [gui.choiceItem(z['id'], z['name']) for z in api.listSecurityGroups()]
    volumeTypes = [gui.choiceItem('-', _('None'))] + [gui.choiceItem(t['id'], t['name']) for t in api.listVolumeTypes()]

    data = [
        {'name': 'availabilityZone', 'values': zones },
        {'name': 'network', 'values': networks },
        {'name': 'flavor', 'values': flavors },
        {'name': 'securityGroups', 'values': securityGroups },
        {'name': 'volumeType', 'values': volumeTypes },
    ]
    logger.debug('Return data: {}'.format(data))
    return data
Ejemplo n.º 23
0
def getResources(parameters):
    """
    This helper is designed as a callback for Project Selector
    """
    from .Provider import OGProvider
    from uds.core.Environment import Environment
    logger.debug('Parameters received by getResources Helper: {0}'.format(parameters))
    env = Environment(parameters['ev'])
    provider = OGProvider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api

    labs = [gui.choiceItem('0', _('All Labs'))] + [gui.choiceItem(l['id'], l['name']) for l in api.getLabs(ou=parameters['ou'])]
    images = [gui.choiceItem(z['id'], z['name']) for z in api.getImages(ou=parameters['ou'])]

    data = [
        {'name': 'lab', 'values': labs },
        {'name': 'image', 'values': images },
    ]
    logger.debug('Return data: {}'.format(data))
    return data
Ejemplo n.º 24
0
def getVolumes(parameters: typing.Dict[str, str]) -> typing.List[typing.Dict[str, typing.Any]]:
    '''
    This helper is designed as a callback for Zone Selector
    '''
    api = getApi(parameters)
    # Source volumes are all available for us
    # volumes = [gui.choiceItem(v['id'], v['name']) for v in api.listVolumes() if v['name'] != '' and v['availability_zone'] == parameters['availabilityZone']]
    volumes = [gui.choiceItem(v['id'], v['name']) for v in api.listVolumes() if v['name'] != '']

    data = [
        {'name': 'volume', 'values': volumes},
    ]
    logger.debug('Return data: %s', data)
    return data
Ejemplo n.º 25
0
    def getGui(self, type_: str) -> typing.List[typing.Any]:
        localGUI = self.addDefaultFields([], ['name', 'short_name', 'comments', 'tags'])

        for field in [{
                'name': 'policy',
                'values': [gui.choiceItem(k, str(v)) for k, v in MetaPool.TYPES.items()],
                'label': ugettext('Policy'),
                'tooltip': ugettext('Service pool policy'),
                'type': gui.InputField.CHOICE_TYPE,
                'order': 100,
            }, {
                'name': 'image_id',
                'values': [gui.choiceImage(-1, '--------', DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in Image.objects.all()]),
                'label': ugettext('Associated Image'),
                'tooltip': ugettext('Image assocciated with this service'),
                'type': gui.InputField.IMAGECHOICE_TYPE,
                'order': 120,
                'tab': ugettext('Display'),
            }, {
                'name': 'servicesPoolGroup_id',
                'values': [gui.choiceImage(-1, _('Default'), DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in ServicePoolGroup.objects.all()]),
                'label': ugettext('Pool group'),
                'tooltip': ugettext('Pool group for this pool (for pool classify on display)'),
                'type': gui.InputField.IMAGECHOICE_TYPE,
                'order': 121,
                'tab': ugettext('Display'),
            }, {
                'name': 'visible',
                'value': True,
                'label': ugettext('Visible'),
                'tooltip': ugettext('If active, metapool will be visible for users'),
                'type': gui.InputField.CHECKBOX_TYPE,
                'order': 123,
                'tab': ugettext('Display'),
            }, {
                'name': 'calendar_message',
                'value': '',
                'label': ugettext('Calendar access denied text'),
                'tooltip': ugettext('Custom message to be shown to users if access is limited by calendar rules.'),
                'type': gui.InputField.TEXT_TYPE,
                'order': 124,
                'tab': ugettext('Display'),
            }]:
            self.addField(localGUI, field)

        return localGUI
Ejemplo n.º 26
0
def getVolumes(parameters):
    """
    This helper is designed as a callback for Zone Selector
    """
    from .Provider import Provider
    from uds.core.Environment import Environment
    logger.debug('Parameters received by getVolumes Helper: {0}'.format(parameters))
    env = Environment(parameters['ev'])
    provider = Provider(env)
    provider.unserialize(parameters['ov'])

    api = provider.api(parameters['project'], parameters['region'])

    volumes = [gui.choiceItem(v['id'], v['name']) for v in api.listVolumes() if v['name'] != '' and v['availability_zone'] == parameters['availabilityZone']]

    data = [
        {'name': 'volume', 'values': volumes },
    ]
    logger.debug('Return data: {}'.format(data))
    return data
Ejemplo n.º 27
0
def getResources(
    parameters: typing.Dict[str, str]
) -> typing.List[typing.Dict[str, typing.Any]]:
    '''
    This helper is designed as a callback for Project Selector
    '''
    api, nameFromSubnets = getApi(parameters)

    zones = [gui.choiceItem(z, z) for z in api.listAvailabilityZones()]
    networks = [
        gui.choiceItem(z['id'], z['name'])
        for z in api.listNetworks(nameFromSubnets=nameFromSubnets)
    ]
    flavors = [gui.choiceItem(z['id'], z['name']) for z in api.listFlavors()]
    securityGroups = [
        gui.choiceItem(z['id'], z['name']) for z in api.listSecurityGroups()
    ]
    volumeTypes = [gui.choiceItem('-', _('None'))] + [
        gui.choiceItem(t['id'], t['name']) for t in api.listVolumeTypes()
    ]

    data = [
        {
            'name': 'availabilityZone',
            'values': zones
        },
        {
            'name': 'network',
            'values': networks
        },
        {
            'name': 'flavor',
            'values': flavors
        },
        {
            'name': 'securityGroups',
            'values': securityGroups
        },
        {
            'name': 'volumeType',
            'values': volumeTypes
        },
    ]
    logger.debug('Return data: %s', data)
    return data
Ejemplo n.º 28
0
class OVirtLinkedService(Service):
    '''
    oVirt Linked clones service. This is based on creating a template from selected vm, and then use it to
    '''
    # : Name to show the administrator. This string will be translated BEFORE
    # : sending it to administration interface, so don't forget to
    # : mark it as _ (using ugettext_noop)
    typeName = _('oVirt/RHEV Linked Clone')
    # : Type used internally to identify this provider
    typeType = 'oVirtLinkedService'
    # : Description shown at administration interface for this provider
    typeDescription = _(
        'oVirt Services based on templates and COW (experimental)')
    # : Icon file used as icon for this provider. This string will be translated
    # : BEFORE sending it to administration interface, so don't forget to
    # : mark it as _ (using ugettext_noop)
    iconFile = 'service.png'

    # Functional related data

    # : If the service provides more than 1 "deployed user" (-1 = no limit,
    # : 0 = ???? (do not use it!!!), N = max number to deploy
    maxDeployed = -1
    # : If we need to generate "cache" for this service, so users can access the
    # : provided services faster. Is usesCache is True, you will need also
    # : set publicationType, do take care about that!
    usesCache = True
    # : Tooltip shown to user when this item is pointed at admin interface, none
    # : because we don't use it
    cacheTooltip = _(
        'Number of desired machines to keep running waiting for a user')
    # : If we need to generate a "Level 2" cache for this service (i.e., L1
    # : could be running machines and L2 suspended machines)
    usesCache_L2 = True
    # : Tooltip shown to user when this item is pointed at admin interface, None
    # : also because we don't use it
    cacheTooltip_L2 = _(
        'Number of desired machines to keep suspended waiting for use')

    # : If the service needs a s.o. manager (managers are related to agents
    # : provided by services itselfs, i.e. virtual machines with actors)
    needsManager = True
    # : If true, the system can't do an automatic assignation of a deployed user
    # : service from this service
    mustAssignManually = False

    # : Types of publications (preparated data for deploys)
    # : In our case, we do no need a publication, so this is None
    publicationType = OVirtPublication
    # : Types of deploys (services in cache and/or assigned to users)
    deployedType = OVirtLinkedDeployment

    # Now the form part
    machine = gui.ChoiceField(label=_("Base Machine"),
                              order=1,
                              tooltip=_('Service base machine'),
                              required=True)
    cluster = gui.ChoiceField(label=_("Cluster"),
                              order=2,
                              fills={
                                  'callbackName': 'ovFillResourcesFromCluster',
                                  'function': oVirtHelpers.getResources,
                                  'parameters': ['cluster', 'ov', 'ev']
                              },
                              tooltip=_("Cluster to contain services"),
                              required=True)

    datastore = gui.ChoiceField(
        label=_("Datastore Domain"),
        rdonly=False,
        order=3,
        tooltip=_('Datastore domain where to publish and put incrementals'),
        required=True)

    minSpaceGB = gui.NumericField(length=3,
                                  label=_('Reserved Space'),
                                  defvalue='32',
                                  order=4,
                                  tooltip=_('Minimal free space in GB'),
                                  required=True)

    memory = gui.NumericField(label=_("Memory (Mb)"),
                              length=4,
                              defvalue=512,
                              rdonly=False,
                              order=5,
                              tooltip=_('Memory assigned to machines'),
                              required=True)

    memoryGuaranteed = gui.NumericField(
        label=_("Memory Guaranteed (Mb)"),
        length=4,
        defvalue=256,
        rdonly=False,
        order=6,
        tooltip=_('Physical memory guaranteed to machines'),
        required=True)

    baseName = gui.TextField(
        label=_('Machine Names'),
        rdonly=False,
        order=6,
        tooltip=('Base name for clones from this machine'),
        required=True)

    lenName = gui.NumericField(
        length=1,
        label=_('Name Length'),
        defvalue=5,
        order=7,
        tooltip=
        _('Size of numeric part for the names of these machines (between 3 and 6)'
          ),
        required=True)

    display = gui.ChoiceField(
        label=_('Display'),
        rdonly=False,
        order=8,
        tooltip=_('Display type (only for administration purposes)'),
        values=[
            gui.choiceItem('spice', 'Spice'),
            gui.choiceItem('vnc', 'Vnc')
        ],
        defvalue='1'  # Default value is the ID of the choicefield
    )

    ov = gui.HiddenField()
    ev = gui.HiddenField(
    )  # We need to keep the env so we can instantiate the Provider

    def initialize(self, values):
        '''
        We check here form values to see if they are valid.

        Note that we check them throught FROM variables, that already has been
        initialized by __init__ method of base class, before invoking this.
        '''
        if values is not None:
            length = int(self.lenName.value)
            if len(self.baseName.value) + length > 15:
                raise Service.ValidationException(
                    _('The length of basename plus length must not be greater than 15'
                      ))
            if self.baseName.value.isdigit():
                raise Service.ValidationException(
                    _('The machine name can\'t be only numbers'))
            if int(self.memory.value) < 256 or int(
                    self.memoryGuaranteed.value) < 256:
                raise Service.ValidationException(
                    _('The minimum allowed memory is 256 Mb'))
            if int(self.memoryGuaranteed.value) > int(self.memory.value):
                self.memoryGuaranteed.value = self.memory.value

    def initGui(self):
        '''
        Loads required values inside
        '''

        # Here we have to use "default values", cause values aren't used at form initialization
        # This is that value is always '', so if we want to change something, we have to do it
        # at defValue
        self.ov.defValue = self.parent().serialize()
        self.ev.defValue = self.parent().env().key()

        machines = self.parent().getMachines()
        vals = []
        for m in machines:
            vals.append(gui.choiceItem(m['id'], m['name']))

        # This is not the same case, values is not the "value" of the field, but
        # the list of values shown because this is a "ChoiceField"
        self.machine.setValues(vals)

        clusters = self.parent().getClusters()
        vals = []
        for c in clusters:
            vals.append(gui.choiceItem(c['id'], c['name']))
        self.cluster.setValues(vals)

    def datastoreHasSpace(self):
        # Get storages for that datacenter
        logger.debug('Checking datastore space for {0}'.format(
            self.datastore.value))
        info = self.parent().getStorageInfo(self.datastore.value)
        logger.debug('Datastore Info: {0}'.format(info))
        availableGB = info['available'] / (1024 * 1024 * 1024)
        if availableGB < self.minSpaceGB.num():
            raise Exception(
                'Not enough free space available: (Needs at least {0} GB and there is only {1} GB '
                .format(self.minSpaceGB.num(), availableGB))

    def sanitizeVmName(self, name):
        '''
        Ovirt only allows machine names with [a-zA-Z0-9_-]
        '''
        import re
        return re.sub("[^a-zA-Z0-9_-]", "_", name)

    def makeTemplate(self, name, comments):
        '''
        Invokes makeTemplate from parent provider, completing params

        Args:
            name: Name to assign to template (must be previously "sanitized"
            comments: Comments (UTF-8) to add to template

        Returns:
            template Id of the template created

        Raises an exception if operation fails.
        '''

        # Checks datastore size
        # Get storages for that datacenter

        self.datastoreHasSpace()
        return self.parent().makeTemplate(name, comments, self.machine.value,
                                          self.cluster.value,
                                          self.datastore.value,
                                          self.display.value)

    def getTemplateState(self, templateId):
        '''
        Invokes getTemplateState from parent provider

        Args:
            templateId: templateId to remove

        Returns nothing

        Raises an exception if operation fails.
        '''
        return self.parent().getTemplateState(templateId)

    def deployFromTemplate(self, name, comments, templateId):
        '''
        Deploys a virtual machine on selected cluster from selected template

        Args:
            name: Name (sanitized) of the machine
            comments: Comments for machine
            templateId: Id of the template to deploy from
            displayType: 'vnc' or 'spice'. Display to use ad oVirt admin interface
            memoryMB: Memory requested for machine, in MB
            guaranteedMB: Minimum memory guaranteed for this machine

        Returns:
            Id of the machine being created form template
        '''
        logger.debug('Deploying from template {0} machine {1}'.format(
            templateId, name))
        self.datastoreHasSpace()
        return self.parent().deployFromTemplate(
            name, comments, templateId, self.cluster.value, self.display.value,
            int(self.memory.value), int(self.memoryGuaranteed.value))

    def removeTemplate(self, templateId):
        '''
        invokes removeTemplate from parent provider
        '''
        return self.parent().removeTemplate(templateId)

    def getMachineState(self, machineId):
        '''
        Invokes getMachineState from parent provider
        (returns if machine is "active" or "inactive"

        Args:
            machineId: If of the machine to get state

        Returns:
            one of this values:
             unassigned, down, up, powering_up, powered_down,
             paused, migrating_from, migrating_to, unknown, not_responding,
             wait_for_launch, reboot_in_progress, saving_state, restoring_state,
             suspended, image_illegal, image_locked or powering_down
             Also can return'unknown' if Machine is not known
        '''
        return self.parent().getMachineState(machineId)

    def startMachine(self, machineId):
        '''
        Tries to start a machine. No check is done, it is simply requested to oVirt.

        This start also "resume" suspended/paused machines

        Args:
            machineId: Id of the machine

        Returns:
        '''
        return self.parent().startMachine(machineId)

    def stopMachine(self, machineId):
        '''
        Tries to start a machine. No check is done, it is simply requested to oVirt

        Args:
            machineId: Id of the machine

        Returns:
        '''
        return self.parent().stopMachine(machineId)

    def suspendMachine(self, machineId):
        '''
        Tries to start a machine. No check is done, it is simply requested to oVirt

        Args:
            machineId: Id of the machine

        Returns:
        '''
        return self.parent().suspendMachine(machineId)

    def removeMachine(self, machineId):
        '''
        Tries to delete a machine. No check is done, it is simply requested to oVirt

        Args:
            machineId: Id of the machine

        Returns:
        '''
        return self.parent().removeMachine(machineId)

    def updateMachineMac(self, machineId, macAddres):
        '''
        Changes the mac address of first nic of the machine to the one specified
        '''
        return self.parent().updateMachineMac(machineId, macAddres)

    def getMacRange(self):
        '''
        Returns de selected mac range
        '''
        return self.parent().getMacRange()

    def getBaseName(self):
        '''
        Returns the base name
        '''
        return self.baseName.value

    def getLenName(self):
        '''
        Returns the length of numbers part
        '''
        return int(self.lenName.value)

    def getDisplay(self):
        '''
        Returns the selected display type (for created machines, for administration
        '''
        return self.display.value
Ejemplo n.º 29
0
from django.utils.translation import ugettext_noop as _
from uds.core.services import ServiceProvider
from uds.core.ui import gui
from uds.core.util import validators

from .LiveService import LiveService
from . import openStack

import logging

__updated__ = '2018-10-22'

logger = logging.getLogger(__name__)

INTERFACE_VALUES = [
    gui.choiceItem('public', 'public'),
    gui.choiceItem('private', 'private'),
    gui.choiceItem('admin', 'admin'),
]


class ProviderLegacy(ServiceProvider):
    '''
    This class represents the sample services provider

    In this class we provide:
       * The Provider functionality
       * The basic configuration parameters for the provider
       * The form fields needed by administrators to configure this provider

       :note: At class level, the translation must be simply marked as so
Ejemplo n.º 30
0
class HTML5VNCTransport(transports.Transport):
    """
    Provides access via VNC to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    typeName = _('HTML5 VNC Experimental')
    typeType = 'HTML5VNCTransport'
    typeDescription = _('VNC protocol using HTML5 client (EXPERIMENTAL)')
    iconFile = 'html5vnc.png'

    ownLink = True
    supportedOss = OsDetector.allOss
    protocol = transports.protocols.VNC
    group = transports.TUNNELED_GROUP

    guacamoleServer = gui.TextField(
        label=_('Tunnel Server'),
        order=1,
        tooltip=
        _('Host of the tunnel server (use http/https & port if needed) as accesible from users'
          ),
        defvalue='https://',
        length=64,
        required=True,
        tab=gui.TUNNEL_TAB)

    username = gui.TextField(
        label=_('Username'),
        order=20,
        tooltip=_('Username for VNC connection authentication.'),
        tab=gui.PARAMETERS_TAB)
    password = gui.PasswordField(
        label=_('Password'),
        order=21,
        tooltip=_('Password for VNC connection authentication'),
        tab=gui.PARAMETERS_TAB)

    vncPort = gui.NumericField(length=22,
                               label=_('VNC Server port'),
                               defvalue='5900',
                               order=2,
                               tooltip=_('Port of the VNC server.'),
                               required=True,
                               tab=gui.PARAMETERS_TAB)

    colorDepth = gui.ChoiceField(
        order=26,
        label=_('Color depth'),
        tooltip=_(
            'Color depth for VNC connection. Use this to control bandwidth.'),
        required=True,
        values=[
            gui.choiceItem('-', 'default'),
            gui.choiceItem('8', '8 bits'),
            gui.choiceItem('16', '16 bits'),
            gui.choiceItem('24', '24 bits'),
            gui.choiceItem('32', '33 bits'),
        ],
        defvalue='-',
        tab=gui.PARAMETERS_TAB)
    swapRedBlue = gui.CheckBoxField(
        label=_('Swap red/blue'),
        order=27,
        tooltip=
        _('Use this if your colours seems incorrect (blue appears red, ..) to swap them.'
          ),
        tab=gui.PARAMETERS_TAB)
    cursor = gui.CheckBoxField(
        label=_('Remote cursor'),
        order=28,
        tooltip=_('If set, force to show remote cursor'),
        tab=gui.PARAMETERS_TAB)
    readOnly = gui.CheckBoxField(
        label=_('Read only'),
        order=29,
        tooltip=_('If set, the connection will be read only'),
        tab=gui.PARAMETERS_TAB)

    ticketValidity = gui.NumericField(
        length=3,
        label=_('Ticket Validity'),
        defvalue='60',
        order=90,
        tooltip=
        _('Allowed time, in seconds, for HTML5 client to reload data from UDS Broker. The default value of 60 is recommended.'
          ),
        required=True,
        minValue=60,
        tab=gui.ADVANCED_TAB)
    forceNewWindow = gui.CheckBoxField(
        label=_('Force new HTML Window'),
        order=91,
        tooltip=
        _('If checked, every connection will try to open its own window instead of reusing the "global" one.'
          ),
        defvalue=gui.FALSE,
        tab=gui.ADVANCED_TAB)

    def initialize(self, values: 'Module.ValuesType'):
        if not values:
            return
        # Strip spaces
        self.guacamoleServer.value = self.guacamoleServer.value.strip()
        if self.guacamoleServer.value[0:4] != 'http':
            raise transports.Transport.ValidationException(
                _('The server must be http or https'))

    def isAvailableFor(self, userService: 'models.UserService',
                       ip: str) -> bool:
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for %s', ip)
        ready = self.cache.get(ip)
        if not ready:
            # Check again for readyness
            if self.testServer(userService, ip, self.vncPort.value) is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def getLink(  # pylint: disable=too-many-locals
            self, userService: 'models.UserService',
            transport: 'models.Transport', ip: str, os: typing.Dict[str, str],
            user: '******', password: str, request: 'HttpRequest') -> str:
        # Build params dict
        params = {
            'protocol': 'vnc',
            'hostname': ip,
            'port': str(self.vncPort.num()),
        }

        if self.username.value.strip():
            params['username'] = self.username.value.strip()

        if self.password.value.strip():
            params['password'] = self.password.value.strip()

        if self.colorDepth.value != '-':
            params['color-depth'] = self.colorDepth.value

        if self.swapRedBlue.isTrue():
            params['swap-red-blue'] = 'true'

        if self.cursor.isTrue():
            params['cursor'] = 'remote'

        if self.readOnly.isTrue():
            params['read-only'] = 'true'

        logger.debug('VNC Params: %s', params)

        scrambler = cryptoManager().randomString(32)
        ticket = models.TicketStore.create(params,
                                           validity=self.ticketValidity.num())

        onw = 'o_n_w={};'.format(hash(
            transport.name)) if self.forceNewWindow.isTrue() else ''
        return str("{}/transport/?{}.{}&{}".format(self.guacamoleServer.value,
                                                   ticket, scrambler, onw))
Ejemplo n.º 31
0
class OVirtProvider(services.ServiceProvider):  # pylint: disable=too-many-public-methods
    """
    This class represents the sample services provider

    In this class we provide:
       * The Provider functionality
       * The basic configuration parameters for the provider
       * The form fields needed by administrators to configure this provider

       :note: At class level, the translation must be simply marked as so
       using ugettext_noop. This is so cause we will translate the string when
       sent to the administration client.

    For this class to get visible at administration client as a provider type,
    we MUST register it at package __init__.

    """
    # : What kind of services we offer, this are classes inherited from Service
    offers = [OVirtLinkedService]
    # : Name to show the administrator. This string will be translated BEFORE
    # : sending it to administration interface, so don't forget to
    # : mark it as _ (using ugettext_noop)
    typeName = _('oVirt/RHEV Platform Provider')
    # : Type used internally to identify this provider
    typeType = 'oVirtPlatform'
    # : Description shown at administration interface for this provider
    typeDescription = _('oVirt platform service provider')
    # : Icon file used as icon for this provider. This string will be translated
    # : BEFORE sending it to administration interface, so don't forget to
    # : mark it as _ (using ugettext_noop)
    iconFile = 'provider.png'

    # now comes the form fields
    # There is always two fields that are requested to the admin, that are:
    # Service Name, that is a name that the admin uses to name this provider
    # Description, that is a short description that the admin gives to this provider
    # Now we are going to add a few fields that we need to use this provider
    # Remember that these are "dummy" fields, that in fact are not required
    # but used for sample purposes
    # If we don't indicate an order, the output order of fields will be
    # "random"
    ovirtVersion = gui.ChoiceField(
        order=1,
        label=_('oVirt Version'),
        tooltip=_('oVirt Server Version'),
        # In this case, the choice can have none value selected by default
        required=True,
        rdonly=False,
        values=[
            gui.choiceItem('4', '4.x'),
        ],
        defvalue='4'  # Default value is the ID of the choicefield
    )

    host = gui.TextField(length=64,
                         label=_('Host'),
                         order=2,
                         tooltip=_('oVirt Server IP or Hostname'),
                         required=True)
    username = gui.TextField(
        length=32,
        label=_('Username'),
        order=3,
        tooltip=_(
            'User with valid privileges on oVirt, (use "user@domain" form)'),
        required=True,
        defvalue='admin@internal')
    password = gui.PasswordField(lenth=32,
                                 label=_('Password'),
                                 order=4,
                                 tooltip=_('Password of the user of oVirt'),
                                 required=True)

    maxPreparingServices = gui.NumericField(
        length=3,
        label=_('Creation concurrency'),
        defvalue='10',
        minValue=1,
        maxValue=65536,
        order=50,
        tooltip=_('Maximum number of concurrently creating VMs'),
        required=True,
        tab=gui.ADVANCED_TAB)
    maxRemovingServices = gui.NumericField(
        length=3,
        label=_('Removal concurrency'),
        defvalue='5',
        minValue=1,
        maxValue=65536,
        order=51,
        tooltip=_('Maximum number of concurrently removing VMs'),
        required=True,
        tab=gui.ADVANCED_TAB)

    timeout = gui.NumericField(
        length=3,
        label=_('Timeout'),
        defvalue='10',
        order=90,
        tooltip=_('Timeout in seconds of connection to oVirt'),
        required=True,
        tab=gui.ADVANCED_TAB)
    macsRange = gui.TextField(
        length=36,
        label=_('Macs range'),
        defvalue='52:54:00:00:00:00-52:54:00:FF:FF:FF',
        order=91,
        rdonly=True,
        tooltip=_('Range of valid macs for UDS managed machines'),
        required=True,
        tab=gui.ADVANCED_TAB)

    # Own variables
    _api: typing.Optional[client.Client] = None

    # oVirt engine, right now, only permits a connection to one server and only one per instance
    # If we want to connect to more than one server, we need keep locked access to api, change api server, etc..
    # We have implemented an "exclusive access" client that will only connect to one server at a time (using locks)
    # and this way all will be fine
    def __getApi(self) -> client.Client:
        """
        Returns the connection API object for oVirt (using ovirtsdk)
        """
        if self._api is None:
            self._api = client.Client(self.host.value, self.username.value,
                                      self.password.value, self.timeout.value,
                                      self.cache)

        return self._api

    # There is more fields type, but not here the best place to cover it
    def initialize(self, values: 'Module.ValuesType') -> None:
        """
        We will use the "autosave" feature for form fields
        """

        # Just reset _api connection variable
        self._api = None

        if values is not None:
            self.macsRange.value = validators.validateMacRange(
                self.macsRange.value)
            self.timeout.value = validators.validateTimeout(self.timeout.value)
            logger.debug(self.host.value)

    def testConnection(self) -> bool:
        """
        Test that conection to oVirt server is fine

        Returns

            True if all went fine, false if id didn't
        """

        return self.__getApi().test()

    def testValidVersion(self):
        """
        Checks that this version of ovirt if "fully functional" and does not needs "patchs'
        """
        return list(self.__getApi().isFullyFunctionalVersion())

    def getMachines(
        self,
        force: bool = False
    ) -> typing.List[typing.MutableMapping[str, typing.Any]]:
        """
        Obtains the list of machines inside oVirt.
        Machines starting with UDS are filtered out

        Args:
            force: If true, force to update the cache, if false, tries to first
            get data from cache and, if valid, return this.

        Returns
            An array of dictionaries, containing:
                'name'
                'id'
                'cluster_id'
        """

        return self.__getApi().getVms(force)

    def getClusters(
        self,
        force: bool = False
    ) -> typing.List[typing.MutableMapping[str, typing.Any]]:
        """
        Obtains the list of clusters inside oVirt.

        Args:
            force: If true, force to update the cache, if false, tries to first
            get data from cache and, if valid, return this.

        Returns
            Filters out clusters not attached to any datacenter
            An array of dictionaries, containing:
                'name'
                'id'
                'datacenter_id'
        """

        return self.__getApi().getClusters(force)

    def getClusterInfo(
            self,
            clusterId: str,
            force: bool = False) -> typing.MutableMapping[str, typing.Any]:
        """
        Obtains the cluster info

        Args:
            datacenterId: Id of the cluster to get information about it
            force: If true, force to update the cache, if false, tries to first
            get data from cache and, if valid, return this.

        Returns

            A dictionary with following values
                'name'
                'id'
                'datacenter_id'
        """
        return self.__getApi().getClusterInfo(clusterId, force)

    def getDatacenterInfo(
            self,
            datacenterId: str,
            force: bool = False) -> typing.MutableMapping[str, typing.Any]:
        """
        Obtains the datacenter info

        Args:
            datacenterId: Id of the datacenter to get information about it
            force: If true, force to update the cache, if false, tries to first
            get data from cache and, if valid, return this.

        Returns

            A dictionary with following values
                'name'
                'id'
                'storage_type' -> ('isisi', 'nfs', ....)
                'storage_format' -> ('v1', v2')
                'description'
                'storage' -> array of dictionaries, with:
                   'id' -> Storage id
                   'name' -> Storage name
                   'type' -> Storage type ('data', 'iso')
                   'available' -> Space available, in bytes
                   'used' -> Space used, in bytes
                   'active' -> True or False

        """
        return self.__getApi().getDatacenterInfo(datacenterId, force)

    def getStorageInfo(
            self,
            storageId: str,
            force: bool = False) -> typing.MutableMapping[str, typing.Any]:
        """
        Obtains the storage info

        Args:
            storageId: Id of the storage to get information about it
            force: If true, force to update the cache, if false, tries to first
            get data from cache and, if valid, return this.

        Returns

            A dictionary with following values
               'id' -> Storage id
               'name' -> Storage name
               'type' -> Storage type ('data', 'iso')
               'available' -> Space available, in bytes
               'used' -> Space used, in bytes
               # 'active' -> True or False --> This is not provided by api?? (api.storagedomains.get)

        """
        return self.__getApi().getStorageInfo(storageId, force)

    def makeTemplate(self, name: str, comments: str, machineId: str,
                     clusterId: str, storageId: str, displayType: str) -> str:
        """
        Publish the machine (makes a template from it so we can create COWs) and returns the template id of
        the creating machine

        Args:
            name: Name of the machine (care, only ascii characters and no spaces!!!)
            machineId: id of the machine to be published
            clusterId: id of the cluster that will hold the machine
            storageId: id of the storage tuat will contain the publication AND linked clones
            displayType: type of display (for oVirt admin interface only)

        Returns
            Raises an exception if operation could not be acomplished, or returns the id of the template being created.
        """
        return self.__getApi().makeTemplate(name, comments, machineId,
                                            clusterId, storageId, displayType)

    def getTemplateState(self, templateId: str) -> str:
        """
        Returns current template state.

        Returned values could be:
            ok
            locked
            removed

        (don't know if ovirt returns something more right now, will test what happens when template can't be published)
        """
        return self.__getApi().getTemplateState(templateId)

    def getMachineState(self, machineId: str) -> str:
        """
        Returns the state of the machine
        This method do not uses cache at all (it always tries to get machine state from oVirt server)

        Args:
            machineId: Id of the machine to get state

        Returns:
            one of this values:
             unassigned, down, up, powering_up, powered_down,
             paused, migrating_from, migrating_to, unknown, not_responding,
             wait_for_launch, reboot_in_progress, saving_state, restoring_state,
             suspended, image_illegal, image_locked or powering_down
             Also can return'unknown' if Machine is not known
        """
        return self.__getApi().getMachineState(machineId)

    def removeTemplate(self, templateId: str) -> None:
        """
        Removes a template from ovirt server

        Returns nothing, and raises an Exception if it fails
        """
        return self.__getApi().removeTemplate(templateId)

    def deployFromTemplate(self, name: str, comments: str, templateId: str,
                           clusterId: str, displayType: str, usbType: str,
                           memoryMB: int, guaranteedMB: int) -> str:
        """
        Deploys a virtual machine on selected cluster from selected template

        Args:
            name: Name (sanitized) of the machine
            comments: Comments for machine
            templateId: Id of the template to deploy from
            clusterId: Id of the cluster to deploy to
            displayType: 'vnc' or 'spice'. Display to use ad oVirt admin interface
            memoryMB: Memory requested for machine, in MB
            guaranteedMB: Minimum memory guaranteed for this machine

        Returns:
            Id of the machine being created form template
        """
        return self.__getApi().deployFromTemplate(name, comments, templateId,
                                                  clusterId, displayType,
                                                  usbType, memoryMB,
                                                  guaranteedMB)

    def startMachine(self, machineId: str) -> None:
        """
        Tries to start a machine. No check is done, it is simply requested to oVirt.

        This start also "resume" suspended/paused machines

        Args:
            machineId: Id of the machine

        Returns:
        """
        self.__getApi().startMachine(machineId)

    def stopMachine(self, machineId: str) -> None:
        """
        Tries to start a machine. No check is done, it is simply requested to oVirt

        Args:
            machineId: Id of the machine

        Returns:
        """
        self.__getApi().stopMachine(machineId)

    def suspendMachine(self, machineId: str) -> None:
        """
        Tries to start a machine. No check is done, it is simply requested to oVirt

        Args:
            machineId: Id of the machine

        Returns:
        """
        self.__getApi().suspendMachine(machineId)

    def removeMachine(self, machineId: str) -> None:
        """
        Tries to delete a machine. No check is done, it is simply requested to oVirt

        Args:
            machineId: Id of the machine

        Returns:
        """
        self.__getApi().removeMachine(machineId)

    def updateMachineMac(self, machineId: str, macAddres: str) -> None:
        """
        Changes the mac address of first nic of the machine to the one specified
        """
        self.__getApi().updateMachineMac(machineId, macAddres)

    def fixUsb(self, machineId: str) -> None:
        self.__getApi().fixUsb(machineId)

    def getMacRange(self) -> str:
        return self.macsRange.value

    def getConsoleConnection(
        self, machineId: str
    ) -> typing.Optional[typing.MutableMapping[str, typing.Any]]:
        return self.__getApi().getConsoleConnection(machineId)

    @staticmethod
    def test(env: 'Environment',
             data: 'Module.ValuesType') -> typing.List[typing.Any]:
        """
        Test ovirt Connectivity

        Args:
            env: environment passed for testing (temporal environment passed)

            data: data passed for testing (data obtained from the form
            definition)

        Returns:
            Array of two elements, first is True of False, depending on test
            (True is all right, false is error),
            second is an String with error, preferably internacionalizated..

        """
        # try:
        #    # We instantiate the provider, but this may fail...
        #    instance = Provider(env, data)
        #    logger.debug('Methuselah has {0} years and is {1} :-)'
        #                 .format(instance.methAge.value, instance.methAlive.value))
        # except ServiceProvider.ValidationException as e:
        #    # If we say that meth is alive, instantiation will
        #    return [False, str(e)]
        # except Exception as e:
        #    logger.exception("Exception caugth!!!")
        #    return [False, str(e)]
        # return [True, _('Nothing tested, but all went fine..')]
        ov = OVirtProvider(env, data)
        if ov.testConnection() is True:
            return ov.testValidVersion()

        return [False, _("Connection failed. Check connection params")]
Ejemplo n.º 32
0
class HTML5RDPTransport(transports.Transport):
    """
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """
    typeName = _('HTML5 RDP')
    typeType = 'HTML5RDPTransport'
    typeDescription = _('RDP protocol using HTML5 client')
    iconFile = 'html5.png'

    ownLink = True
    supportedOss = OsDetector.allOss
    protocol = transports.protocols.RDP
    group = transports.TUNNELED_GROUP

    guacamoleServer = gui.TextField(label=_('Tunnel Server'), order=1, tooltip=_('Host of the tunnel server (use http/https & port if needed) as accesible from users'), defvalue='https://', length=64, required=True, tab=gui.TUNNEL_TAB)
    useEmptyCreds = gui.CheckBoxField(label=_('Empty creds'), order=2, tooltip=_('If checked, the credentials used to connect will be emtpy'), tab=gui.CREDENTIALS_TAB)
    fixedName = gui.TextField(label=_('Username'), order=3, tooltip=_('If not empty, this username will be always used as credential'), tab=gui.CREDENTIALS_TAB)
    fixedPassword = gui.PasswordField(label=_('Password'), order=4, tooltip=_('If not empty, this password will be always used as credential'), tab=gui.CREDENTIALS_TAB)
    withoutDomain = gui.CheckBoxField(label=_('Without Domain'), order=5, tooltip=_('If checked, the domain part will always be emptied (to connecto to xrdp for example is needed)'), tab=gui.CREDENTIALS_TAB)
    fixedDomain = gui.TextField(label=_('Domain'), order=6, tooltip=_('If not empty, this domain will be always used as credential (used as DOMAIN\\user)'), tab=gui.CREDENTIALS_TAB)
    wallpaper = gui.CheckBoxField(label=_('Show wallpaper'), order=20, tooltip=_('If checked, the wallpaper and themes will be shown on machine (better user experience, more bandwidth)'), tab=gui.PARAMETERS_TAB)
    desktopComp = gui.CheckBoxField(label=_('Allow Desk.Comp.'), order=22, tooltip=_('If checked, desktop composition will be allowed'), tab=gui.PARAMETERS_TAB)
    smooth = gui.CheckBoxField(label=_('Font Smoothing'), order=23, tooltip=_('If checked, fonts smoothing will be allowed (windows clients only)'), tab=gui.PARAMETERS_TAB)
    enableAudio = gui.CheckBoxField(label=_('Enable Audio'), order=24, tooltip=_('If checked, the audio will be redirected to client (if client browser supports it)'), tab=gui.PARAMETERS_TAB)
    enablePrinting = gui.CheckBoxField(label=_('Enable Printing'), order=25, tooltip=_('If checked, the printing will be redirected to client (if client browser supports it)'), tab=gui.PARAMETERS_TAB)
    enableFileSharing = gui.CheckBoxField(label=_('Enable File Sharing'), order=8, tooltip=_('If checked, the user will be able to upload/download files (if client browser supports it)'), tab=gui.PARAMETERS_TAB)
    serverLayout = gui.ChoiceField(
        order=26,
        label=_('Layout'),
        tooltip=_('Keyboards Layout of server'),
        required=True,
        values=[
            gui.choiceItem('-', 'default'),
            gui.choiceItem('en-us-qwerty', _('English (US) keyboard')),
            gui.choiceItem('en-gb-qwerty', _('English (GB) keyboard')),
            gui.choiceItem('es-es-qwerty', _('Spanish keyboard')),
            gui.choiceItem('latam-qwerty', _('Latin American keyboard')),
            gui.choiceItem('de-de-qwertz', _('German keyboard (qwertz)')),
            gui.choiceItem('fr-fr-azerty', _('French keyboard (azerty)')),
            gui.choiceItem('fr-ch-qwertz', _('Swiss French keyboard (qwertz)')),
            gui.choiceItem('de-ch-qwertz', _('Swiss German keyboard (qwertz)')),
            gui.choiceItem('it-it-qwerty', _('Italian keyboard')),
            gui.choiceItem('sv-se-qwerty', _('Swedish keyboard')),
            gui.choiceItem('ja-jp-qwerty', _('Japanese keyboard')),
            gui.choiceItem('pt-br-qwerty', _('Brazilian keyboard')),
            gui.choiceItem('failsafe', _('Failsafe')),
        ],
        defvalue='-',
        tab=gui.PARAMETERS_TAB
    )
    security = gui.ChoiceField(
        order=27,
        label=_('Security'),
        tooltip=_('Connection security mode for Guacamole RDP connection'),
        required=True,
        values=[
            gui.choiceItem('any', _('Any (Allow the server to choose the type of auth)')),
            gui.choiceItem('rdp', _('RDP (Standard RDP encryption. Should be supported by all servers)')),
            gui.choiceItem('nla', _('NLA (Network Layer authentication. Requires VALID username&password, or connection will fail)')),
            gui.choiceItem('tls', _('TLS (Transport Security Layer encryption)')),
        ],
        defvalue='rdp',
        tab=gui.PARAMETERS_TAB
    )

    ticketValidity = gui.NumericField(
        length=3,
        label=_('Ticket Validity'),
        defvalue='60',
        order=90,
        tooltip=_('Allowed time, in seconds, for HTML5 client to reload data from UDS Broker. The default value of 60 is recommended.'),
        required=True,
        minValue=60,
        tab=gui.ADVANCED_TAB
    )
    forceNewWindow = gui.CheckBoxField(
        label=_('Force new HTML Window'),
        order=91,
        tooltip=_('If checked, every connection will try to open its own window instead of reusing the "global" one.'),
        defvalue=gui.FALSE,
        tab=gui.ADVANCED_TAB
    )

    def initialize(self, values: 'Module.ValuesType'):
        if not values:
            return
        # Strip spaces
        self.guacamoleServer.value = self.guacamoleServer.value.strip()
        if self.guacamoleServer.value[0:4] != 'http':
            raise transports.Transport.ValidationException(_('The server must be http or https'))
        if self.useEmptyCreds.isTrue() and self.security.value != 'rdp':
            raise transports.Transport.ValidationException(_('Empty credentials (on Credentials tab) is only allowed with Security level (on Parameters tab) set to "RDP"'))

    # Same check as normal RDP transport
    def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool:
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for %s', ip)
        ready = self.cache.get(ip)
        if not ready:
            # Check again for readyness
            if self.testServer(userService, ip, '3389') is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def processedUser(self, userService: 'models.UserService', user: '******') -> str:
        v = self.processUserAndPassword(userService, user, '')
        return v['username']

    def processUserAndPassword(self, userService: 'models.UserService', user: '******', password: str) -> typing.Dict[str, str]:
        username: str = user.getUsernameForAuth()

        if self.fixedName.value != '':
            username = self.fixedName.value

        proc = username.split('@')
        domain = proc[1] if len(proc) > 1 else ''
        username = proc[0]

        if self.fixedPassword.value != '':
            password = self.fixedPassword.value

        if self.fixedDomain.value != '':
            domain = self.fixedDomain.value

        if self.useEmptyCreds.isTrue():
            username, password, domain = '', '', ''

        # If no domain to be transfered, set it to ''
        if self.withoutDomain.isTrue():
            domain = ''

        if '.' in domain:  # Dotter domain form
            username = username + '@' + domain
            domain = ''

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(username, password)

        return {'protocol': self.protocol, 'username': username, 'password': password, 'domain': domain}

    def getLink(  # pylint: disable=too-many-locals
            self,
            userService: 'models.UserService',
            transport: 'models.Transport',
            ip: str,
            os: typing.Dict[str, str],
            user: '******',
            password: str,
            request: 'HttpRequest'
        ) -> str:
        credsInfo = self.processUserAndPassword(userService, user, password)
        username, password, domain = credsInfo['username'], credsInfo['password'], credsInfo['domain']

        if domain != '':
            username = domain + '\\' + username

        scrambler = cryptoManager().randomString(32)
        passwordCrypted = cryptoManager().symCrypt(password, scrambler)

        # Build params dict
        params = {
            'protocol': 'rdp',
            'hostname': ip,
            'username': username,
            'password': passwordCrypted,
            'ignore-cert': 'true',
            'security': self.security.value,
            'drive-path': '/share/{}'.format(user.uuid),
            'create-drive-path': 'true'
        }

        if self.enableFileSharing.isTrue():
            params['enable-drive'] = 'true'

        if self.serverLayout.value != '-':
            params['server-layout'] = self.serverLayout.value

        if self.enableAudio.isTrue() is False:
            params['disable-audio'] = 'true'

        if self.enablePrinting.isTrue() is True:
            params['enable-printing'] = 'true'
            params['printer-name'] = 'UDS-Printer'

        if self.wallpaper.isTrue() is True:
            params['enable-wallpaper'] = 'true'

        if self.desktopComp.isTrue() is True:
            params['enable-desktop-composition'] = 'true'

        if self.smooth.isTrue() is True:
            params['enable-font-smoothing'] = 'true'

        logger.debug('RDP Params: %s', params)

        ticket = models.TicketStore.create(params, validity=self.ticketValidity.num())

        return HttpResponseRedirect(
            "{}/transport/{}?{}.{}&{}".format(
                self.guacamoleServer.value,
                'o_n_w' if self.forceNewWindow.isTrue() else '',
                ticket,
                scrambler,
                'javascript:window.close();'
            )
        )
Ejemplo n.º 33
0
class ServiceOne(Service):
    '''
    Basic service, the first part (variables) include the description of the service.
    
    Remember to fill all variables needed, but at least you must define:
        * typeName
        * typeType
        * typeDescription
        * iconFile (defaults to service.png)
        * publicationType, type of publication in case it needs publication. 
          If this is not provided, core will assume that the service do not 
          needs publishing.
        * deployedType, type of deployed user service. Do not forget this!!!
        
    The rest of them can be ommited, but its recommended that you fill all
    declarations shown in this sample (that in fact, are all)
    
    This description informs the core what this service really provides,
    and how this is done. Look at description of class variables for more
    information.
    
    '''
    #: Name to show the administrator. This string will be translated BEFORE
    #: sending it to administration interface, so don't forget to
    #: mark it as _ (using ugettext_noop)
    typeName = _('Sample Service One')
    #: Type used internally to identify this provider
    typeType = 'SampleService1'
    #: Description shown at administration interface for this provider
    typeDescription = _('Sample (and dummy) service ONE')
    #: Icon file used as icon for this provider. This string will be translated
    #: BEFORE sending it to administration interface, so don't forget to
    #: mark it as _ (using ugettext_noop)
    iconFile = 'service.png'

    # Functional related data

    #: If the service provides more than 1 "deployed user" (-1 = no limit,
    #: 0 = ???? (do not use it!!!), N = max number to deploy
    maxDeployed = -1
    #: If we need to generate "cache" for this service, so users can access the
    #: provided services faster. Is usesCache is True, you will need also
    #: set publicationType, do take care about that!
    usesCache = False
    #: Tooltip shown to user when this item is pointed at admin interface, none
    #: because we don't use it
    cacheTooltip = _('None')
    #: If we need to generate a "Level 2" cache for this service (i.e., L1
    #: could be running machines and L2 suspended machines)
    usesCache_L2 = False
    #: Tooltip shown to user when this item is pointed at admin interface, None
    #: also because we don't use it
    cacheTooltip_L2 = _('None')

    #: If the service needs a s.o. manager (managers are related to agents
    #: provided by services itselfs, i.e. virtual machines with actors)
    needsManager = False
    #: If true, the system can't do an automatic assignation of a deployed user
    #: service from this service
    mustAssignManually = False

    #: Types of publications (preparated data for deploys)
    #: In our case, we do no need a publication, so this is None
    publicationType = None
    #: Types of deploys (services in cache and/or assigned to users)
    deployedType = SampleUserDeploymentOne

    # Now the form part, this service will have only two "dummy" fields
    # If we don't indicate an order, the output order of fields will be
    # "random"

    colour = gui.ChoiceField(
        order=1,
        label=_('Colour'),
        tooltip=_('Colour of the field'),
        # In this case, the choice can have none value selected by default
        required=True,
        values=[
            gui.choiceItem('red', 'Red'),
            gui.choiceItem('green', 'Green'),
            gui.choiceItem('blue', 'Blue'),
            gui.choiceItem('nonsense', 'Blagenta')
        ],
        defvalue='1'  # Default value is the ID of the choicefield
    )

    passw = gui.PasswordField(
        order=2,
        label=_('Password'),
        tooltip=_('Password for testing purposes'),
        required=True,
        defvalue='1234'  #: Default password are nonsense?? :-)
    )

    baseName = gui.TextField(
        order=3,
        label=_('Services names'),
        tooltip=_('Base name for this user services'),
        # In this case, the choice can have none value selected by default
        required=True,
        defvalue=''  # Default value is the ID of the choicefield
    )

    def initialize(self, values):
        '''
        We check here form values to see if they are valid.
        
        Note that we check them throught FROM variables, that already has been
        initialized by __init__ method of base class, before invoking this.
        '''

        # We don't need to check anything, bat because this is a sample, we do
        # As in provider, we receive values only at new Service creation,
        # so we only need to validate params if values is not None
        if values is not None:
            if self.colour.value == 'nonsense':
                raise Service.ValidationException(
                    'The selected colour is invalid!!!')

    # Services itself are non testeable right now, so we don't even have
    # to provide one!!!

    # Congratulations!!!, the needed part of your first simple service is done!
    # Now you can go to administration panel, and check it
    #
    # From now onwards, we implement our own methods, that will be used by,
    # for example, services derived from this provider

    def getColour(self):
        '''
        Simply returns colour, for deployed user services.
        
        Remember that choiceField.value returns the id part of the ChoiceItem
        '''
        return self.colour.value

    def getPassw(self):
        '''
        Simply returns passwd, for deloyed user services
        '''
        return self.passw.value

    def getBaseName(self):
        '''
        '''
        return self.baseName.value
Ejemplo n.º 34
0
from django.utils.translation import ugettext_noop as _
from uds.core.services import ServiceProvider
from uds.core.ui import gui
from uds.core.util import validators

from .LiveService import LiveService
from . import openStack

import logging

__updated__ = '2016-04-25'

logger = logging.getLogger(__name__)

INTERFACE_VALUES = [
    gui.choiceItem('public', 'public'),
    gui.choiceItem('private', 'private'),
    gui.choiceItem('admin', 'admin'),
]


class Provider(ServiceProvider):
    """
    This class represents the sample services provider

    In this class we provide:
       * The Provider functionality
       * The basic configuration parameters for the provider
       * The form fields needed by administrators to configure this provider

       :note: At class level, the translation must be simply marked as so
Ejemplo n.º 35
0
 def listAssignables(self, item: ServicePool) -> typing.Any:
     service = item.service.getInstance()
     return [gui.choiceItem(i[0], i[1]) for i in service.listAssignables()]
Ejemplo n.º 36
0
    def getGui(self, type_: str) -> typing.List[typing.Any]:
        # if OSManager.objects.count() < 1:  # No os managers, can't create db
        #    raise ResponseError(ugettext('Create at least one OS Manager before creating a new service pool'))
        if Service.objects.count() < 1:
            raise ResponseError(
                ugettext(
                    'Create at least a service before creating a new service pool'
                ))

        g = self.addDefaultFields([],
                                  ['name', 'short_name', 'comments', 'tags'])

        for f in [
            {
                'name':
                'service_id',
                'values': [gui.choiceItem('', '')] + gui.sortedChoices([
                    gui.choiceItem(v.uuid, v.provider.name + '\\' + v.name)
                    for v in Service.objects.all()
                ]),
                'label':
                ugettext('Base service'),
                'tooltip':
                ugettext('Service used as base of this service pool'),
                'type':
                gui.InputField.CHOICE_TYPE,
                'rdonly':
                True,
                'order':
                100,  # Ensueres is At end
            },
            {
                'name':
                'osmanager_id',
                'values': [gui.choiceItem(-1, '')] + gui.sortedChoices([
                    gui.choiceItem(v.uuid, v.name)
                    for v in OSManager.objects.all()
                ]),
                'label':
                ugettext('OS Manager'),
                'tooltip':
                ugettext('OS Manager used as base of this service pool'),
                'type':
                gui.InputField.CHOICE_TYPE,
                'rdonly':
                True,
                'order':
                101,
            },
            {
                'name':
                'allow_users_remove',
                'value':
                False,
                'label':
                ugettext('Allow removal by users'),
                'tooltip':
                ugettext(
                    'If active, the user will be allowed to remove the service "manually". Be careful with this, because the user will have the "power" to delete it\'s own service'
                ),
                'type':
                gui.InputField.CHECKBOX_TYPE,
                'order':
                111,
                'tab':
                ugettext('Advanced'),
            },
            {
                'name':
                'allow_users_reset',
                'value':
                False,
                'label':
                ugettext('Allow reset by users'),
                'tooltip':
                ugettext(
                    'If active, the user will be allowed to reset the service'
                ),
                'type':
                gui.InputField.CHECKBOX_TYPE,
                'order':
                112,
                'tab':
                ugettext('Advanced'),
            },
            {
                'name':
                'ignores_unused',
                'value':
                False,
                'label':
                ugettext('Ignores unused'),
                'tooltip':
                ugettext(
                    'If the option is enabled, UDS will not attempt to detect and remove the user services assigned but not in use.'
                ),
                'type':
                gui.InputField.CHECKBOX_TYPE,
                'order':
                113,
                'tab':
                ugettext('Advanced'),
            },
            {
                'name':
                'image_id',
                'values':
                [gui.choiceImage(-1, '--------', DEFAULT_THUMB_BASE64)] +
                gui.sortedChoices([
                    gui.choiceImage(v.uuid, v.name, v.thumb64)
                    for v in Image.objects.all()
                ]),
                'label':
                ugettext('Associated Image'),
                'tooltip':
                ugettext('Image assocciated with this service'),
                'type':
                gui.InputField.IMAGECHOICE_TYPE,
                'order':
                120,
                'tab':
                ugettext('Display'),
            },
            {
                'name':
                'pool_group_id',
                'values':
                [gui.choiceImage(-1, _('Default'), DEFAULT_THUMB_BASE64)] +
                gui.sortedChoices([
                    gui.choiceImage(v.uuid, v.name, v.thumb64)
                    for v in ServicePoolGroup.objects.all()
                ]),
                'label':
                ugettext('Pool group'),
                'tooltip':
                ugettext(
                    'Pool group for this pool (for pool classify on display)'),
                'type':
                gui.InputField.IMAGECHOICE_TYPE,
                'order':
                121,
                'tab':
                ugettext('Display'),
            },
            {
                'name':
                'visible',
                'value':
                True,
                'label':
                ugettext('Visible'),
                'tooltip':
                ugettext('If active, transport will be visible for users'),
                'type':
                gui.InputField.CHECKBOX_TYPE,
                'order':
                107,
                'tab':
                ugettext('Display'),
            },
            {
                'name':
                'initial_srvs',
                'value':
                '0',
                'minValue':
                '0',
                'label':
                ugettext('Initial available services'),
                'tooltip':
                ugettext('Services created initially for this service pool'),
                'type':
                gui.InputField.NUMERIC_TYPE,
                'order':
                130,
                'tab':
                ugettext('Availability'),
            },
            {
                'name':
                'cache_l1_srvs',
                'value':
                '0',
                'minValue':
                '0',
                'label':
                ugettext('Services to keep in cache'),
                'tooltip':
                ugettext(
                    'Services kept in cache for improved user service assignation'
                ),
                'type':
                gui.InputField.NUMERIC_TYPE,
                'order':
                131,
                'tab':
                ugettext('Availability'),
            },
            {
                'name':
                'cache_l2_srvs',
                'value':
                '0',
                'minValue':
                '0',
                'label':
                ugettext('Services to keep in L2 cache'),
                'tooltip':
                ugettext(
                    'Services kept in cache of level2 for improved service generation'
                ),
                'type':
                gui.InputField.NUMERIC_TYPE,
                'order':
                132,
                'tab':
                ugettext('Availability'),
            },
            {
                'name':
                'max_srvs',
                'value':
                '0',
                'minValue':
                '1',
                'label':
                ugettext('Maximum number of services to provide'),
                'tooltip':
                ugettext(
                    'Maximum number of service (assigned and L1 cache) that can be created for this service'
                ),
                'type':
                gui.InputField.NUMERIC_TYPE,
                'order':
                133,
                'tab':
                ugettext('Availability'),
            },
            {
                'name':
                'show_transports',
                'value':
                True,
                'label':
                ugettext('Show transports'),
                'tooltip':
                ugettext(
                    'If active, alternative transports for user will be shown'
                ),
                'type':
                gui.InputField.CHECKBOX_TYPE,
                'tab':
                ugettext('Advanced'),
                'order':
                130,
            },
            {
                'name':
                'account_id',
                'values': [gui.choiceItem(-1, '')] + gui.sortedChoices([
                    gui.choiceItem(v.uuid, v.name)
                    for v in Account.objects.all()
                ]),
                'label':
                ugettext('Accounting'),
                'tooltip':
                ugettext('Account associated to this service pool'),
                'type':
                gui.InputField.CHOICE_TYPE,
                'tab':
                ugettext('Advanced'),
                'order':
                131,
            }
        ]:
            self.addField(g, f)

        return g
Ejemplo n.º 37
0
class HTML5RDPTransport(transports.Transport):
    """
    Provides access via RDP to service.
    This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
    """

    typeName = _('HTML5 RDP')
    typeType = 'HTML5RDPTransport'
    typeDescription = _('RDP protocol using HTML5 client')
    iconFile = 'html5.png'

    ownLink = True
    supportedOss = OsDetector.allOss
    protocol = transports.protocols.RDP
    group = transports.TUNNELED_GROUP

    guacamoleServer = gui.TextField(
        label=_('Tunnel Server'),
        order=1,
        tooltip=
        _('Host of the tunnel server (use http/https & port if needed) as accesible from users'
          ),
        defvalue='https://',
        length=64,
        required=True,
        tab=gui.TUNNEL_TAB,
    )

    useGlyptodonTunnel = gui.CheckBoxField(
        label=_('Use Glyptodon Enterprise tunnel'),
        order=2,
        tooltip=
        _('If checked, UDS will use Glyptodon Enterprise Tunnel for HTML tunneling instead of UDS Tunnel'
          ),
        tab=gui.TUNNEL_TAB,
    )

    useEmptyCreds = gui.CheckBoxField(
        label=_('Empty creds'),
        order=3,
        tooltip=_('If checked, the credentials used to connect will be emtpy'),
        tab=gui.CREDENTIALS_TAB,
    )
    fixedName = gui.TextField(
        label=_('Username'),
        order=4,
        tooltip=_(
            'If not empty, this username will be always used as credential'),
        tab=gui.CREDENTIALS_TAB,
    )
    fixedPassword = gui.PasswordField(
        label=_('Password'),
        order=5,
        tooltip=_(
            'If not empty, this password will be always used as credential'),
        tab=gui.CREDENTIALS_TAB,
    )
    withoutDomain = gui.CheckBoxField(
        label=_('Without Domain'),
        order=6,
        tooltip=
        _('If checked, the domain part will always be emptied (to connecto to xrdp for example is needed)'
          ),
        tab=gui.CREDENTIALS_TAB,
    )
    fixedDomain = gui.TextField(
        label=_('Domain'),
        order=7,
        tooltip=
        _('If not empty, this domain will be always used as credential (used as DOMAIN\\user)'
          ),
        tab=gui.CREDENTIALS_TAB,
    )
    wallpaper = gui.CheckBoxField(
        label=_('Show wallpaper'),
        order=20,
        tooltip=
        _('If checked, the wallpaper and themes will be shown on machine (better user experience, more bandwidth)'
          ),
        tab=gui.PARAMETERS_TAB,
    )
    desktopComp = gui.CheckBoxField(
        label=_('Allow Desk.Comp.'),
        order=22,
        tooltip=_('If checked, desktop composition will be allowed'),
        tab=gui.PARAMETERS_TAB,
    )
    smooth = gui.CheckBoxField(
        label=_('Font Smoothing'),
        order=23,
        tooltip=_(
            'If checked, fonts smoothing will be allowed (windows clients only)'
        ),
        tab=gui.PARAMETERS_TAB,
    )
    enableAudio = gui.CheckBoxField(
        label=_('Enable Audio'),
        order=24,
        tooltip=
        _('If checked, the audio will be redirected to remote session (if client browser supports it)'
          ),
        tab=gui.PARAMETERS_TAB,
        defvalue=gui.TRUE,
    )
    enableAudioInput = gui.CheckBoxField(
        label=_('Enable Microphone'),
        order=24,
        tooltip=
        _('If checked, the microphone will be redirected to remote session (if client browser supports it)'
          ),
        tab=gui.PARAMETERS_TAB,
    )
    enablePrinting = gui.CheckBoxField(
        label=_('Enable Printing'),
        order=25,
        tooltip=
        _('If checked, the printing will be redirected to remote session (if client browser supports it)'
          ),
        tab=gui.PARAMETERS_TAB,
    )
    enableFileSharing = gui.ChoiceField(
        label=_('File Sharing'),
        order=22,
        tooltip=_('File upload/download redirection policy'),
        defvalue='false',
        values=[
            {
                'id': 'false',
                'text': 'Disable file sharing'
            },
            {
                'id': 'down',
                'text': 'Allow download only'
            },
            {
                'id': 'up',
                'text': 'Allow upload only'
            },
            {
                'id': 'true',
                'text': 'Enable file sharing'
            },
        ],
        tab=gui.PARAMETERS_TAB,
    )

    serverLayout = gui.ChoiceField(
        order=26,
        label=_('Layout'),
        tooltip=_('Keyboards Layout of server'),
        required=True,
        values=[
            gui.choiceItem('-', 'default'),
            gui.choiceItem('en-us-qwerty', _('English (US) keyboard')),
            gui.choiceItem('en-gb-qwerty', _('English (GB) keyboard')),
            gui.choiceItem('es-es-qwerty', _('Spanish keyboard')),
            gui.choiceItem('es-latam-qwerty', _('Latin American keyboard')),
            gui.choiceItem('de-de-qwertz', _('German keyboard (qwertz)')),
            gui.choiceItem('fr-fr-azerty', _('French keyboard (azerty)')),
            gui.choiceItem('fr-ch-qwertz',
                           _('Swiss French keyboard (qwertz)')),
            gui.choiceItem('de-ch-qwertz',
                           _('Swiss German keyboard (qwertz)')),
            gui.choiceItem('it-it-qwerty', _('Italian keyboard')),
            gui.choiceItem('sv-se-qwerty', _('Swedish keyboard')),
            gui.choiceItem('ja-jp-qwerty', _('Japanese keyboard')),
            gui.choiceItem('pt-br-qwerty', _('Brazilian keyboard')),
            gui.choiceItem('failsafe', _('Failsafe')),
        ],
        defvalue='-',
        tab=gui.PARAMETERS_TAB,
    )
    security = gui.ChoiceField(
        order=27,
        label=_('Security'),
        tooltip=_('Connection security mode for Guacamole RDP connection'),
        required=True,
        values=[
            gui.choiceItem(
                'any', _('Any (Allow the server to choose the type of auth)')),
            gui.choiceItem(
                'rdp',
                _('RDP (Standard RDP encryption. Should be supported by all servers)'
                  ),
            ),
            gui.choiceItem(
                'nla',
                _('NLA (Network Layer authentication. Requires VALID username&password, or connection will fail)'
                  ),
            ),
            gui.choiceItem(
                'nla-ext',
                _('NLA extended (Network Layer authentication. Requires VALID username&password, or connection will fail)'
                  ),
            ),
            gui.choiceItem('tls',
                           _('TLS (Transport Security Layer encryption)')),
        ],
        defvalue='any',
        tab=gui.PARAMETERS_TAB,
    )

    ticketValidity = gui.NumericField(
        length=3,
        label=_('Ticket Validity'),
        defvalue='60',
        order=90,
        tooltip=
        _('Allowed time, in seconds, for HTML5 client to reload data from UDS Broker. The default value of 60 is recommended.'
          ),
        required=True,
        minValue=60,
        tab=gui.ADVANCED_TAB,
    )

    forceNewWindow = gui.ChoiceField(
        order=91,
        label=_('Force new HTML Window'),
        tooltip=_('Select windows behavior for new connections on HTML5'),
        required=True,
        values=[
            gui.choiceItem(
                gui.FALSE,
                _('Open every connection on the same window, but keeps UDS window.'
                  ),
            ),
            gui.choiceItem(
                gui.TRUE,
                _('Force every connection to be opened on a new window.')),
            gui.choiceItem(
                'overwrite',
                _('Override UDS window and replace it with the connection.'),
            ),
        ],
        defvalue=gui.FALSE,
        tab=gui.ADVANCED_TAB,
    )

    customGEPath = gui.TextField(
        label=_('Glyptodon Enterprise context path'),
        order=92,
        tooltip=
        _('Customized path for Glyptodon Enterprise tunnel. (Only valid for Glyptodon Enterprise Tunnel)'
          ),
        defvalue='/',
        length=128,
        required=False,
        tab=gui.ADVANCED_TAB,
    )

    def initialize(self, values: 'Module.ValuesType'):
        if not values:
            return
        # Strip spaces
        self.guacamoleServer.value = self.guacamoleServer.value.strip()
        if self.guacamoleServer.value[0:4] != 'http':
            raise transports.Transport.ValidationException(
                _('The server must be http or https'))
        if self.useEmptyCreds.isTrue() and self.security.value != 'rdp':
            raise transports.Transport.ValidationException(
                _('Empty credentials (on Credentials tab) is only allowed with Security level (on Parameters tab) set to "RDP"'
                  ))

    # Same check as normal RDP transport
    def isAvailableFor(self, userService: 'models.UserService',
                       ip: str) -> bool:
        """
        Checks if the transport is available for the requested destination ip
        Override this in yours transports
        """
        logger.debug('Checking availability for %s', ip)
        ready = self.cache.get(ip)
        if not ready:
            # Check again for readyness
            if self.testServer(userService, ip, '3389') is True:
                self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
                return True
            self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
        return ready == 'Y'

    def processedUser(self, userService: 'models.UserService',
                      user: '******') -> str:
        v = self.processUserAndPassword(userService, user, '')
        return v['username']

    def processUserAndPassword(self, userService: 'models.UserService',
                               user: '******',
                               password: str) -> typing.Dict[str, str]:
        username: str = user.getUsernameForAuth()

        if self.fixedName.value != '':
            username = self.fixedName.value

        proc = username.split('@')
        domain = proc[1] if len(proc) > 1 else ''
        username = proc[0]

        if self.fixedPassword.value != '':
            password = self.fixedPassword.value

        azureAd = False
        if self.fixedDomain.value != '':
            if self.fixedDomain.value.lower() == 'azuread':
                azureAd = True
            else:
                domain = self.fixedDomain.value

        if self.useEmptyCreds.isTrue():
            username, password, domain = '', '', ''

        # If no domain to be transfered, set it to ''
        if self.withoutDomain.isTrue():
            domain = ''

        if '.' in domain:  # Dotter domain form
            username = username + '@' + domain
            domain = ''

        # If AzureAD, include it on username
        if azureAd:
            username = '******' + username

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(
            username, password)

        return {
            'protocol': self.protocol,
            'username': username,
            'password': password,
            'domain': domain,
        }

    def getLink(  # pylint: disable=too-many-locals
        self,
        userService: 'models.UserService',
        transport: 'models.Transport',
        ip: str,
        os: typing.Dict[str, str],
        user: '******',
        password: str,
        request: 'HttpRequest',
    ) -> str:
        credsInfo = self.processUserAndPassword(userService, user, password)
        username, password, domain = (
            credsInfo['username'],
            credsInfo['password'],
            credsInfo['domain'],
        )

        scrambler = cryptoManager().randomString(32)
        passwordCrypted = cryptoManager().symCrypt(password, scrambler)

        # Build params dict
        params = {
            'protocol': 'rdp',
            'hostname': ip,
            'username': username,
            'password': passwordCrypted,
            'resize-method': 'display-update',
            'ignore-cert': 'true',
            'security': self.security.value,
            'drive-path': '/share/{}'.format(user.uuid),
            'create-drive-path': 'true',
            'ticket-info': {
                'userService': userService.uuid,
                'user': userService.user.uuid,
            },
        }

        if False:  # Future imp
            sanitize = lambda x: re.sub("[^a-zA-Z0-9_-]", "_", x)
            params['recording-path'] = (
                '/share/recording/' + sanitize(user.manager.name) + '_' +
                sanitize(user.name) + '/' +
                getSqlDatetime().strftime('%Y%m%d-%H%M'))
            params['create-recording-path'] = 'true'

        if domain:
            params['domain'] = domain

        if self.enableFileSharing.value == 'true':
            params['enable-drive'] = 'true'
        elif self.enableFileSharing.value == 'down':
            params['enable-drive'] = 'true'
            params['disable-upload'] = 'true'
        elif self.enableFileSharing.value == 'up':
            params['enable-drive'] = 'true'
            params['disable-download'] = 'true'

        if self.serverLayout.value != '-':
            params['server-layout'] = self.serverLayout.value

        if not self.enableAudio.isTrue():
            params['disable-audio'] = 'true'
        elif self.enableAudioInput.isTrue():
            params['enable-audio-input'] = 'true'

        if self.enablePrinting.isTrue():
            params['enable-printing'] = 'true'
            params['printer-name'] = 'UDS-Printer'

        if self.wallpaper.isTrue():
            params['enable-wallpaper'] = 'true'

        if self.desktopComp.isTrue():
            params['enable-desktop-composition'] = 'true'

        if self.smooth.isTrue():
            params['enable-font-smoothing'] = 'true'

        logger.debug('RDP Params: %s', params)

        ticket = models.TicketStore.create(params,
                                           validity=self.ticketValidity.num())

        onw = ''
        if self.forceNewWindow.value == gui.TRUE:
            onw = '&o_n_w={}'
        elif self.forceNewWindow.value == 'overwrite':
            onw = '&o_s_w=yes'
        onw = onw.format(hash(transport.name))
        path = (self.customGEPath.value
                if self.useGlyptodonTunnel.isTrue() else '/guacamole')
        # Remove trailing /
        if path[-1] == '/':
            path = path[:-1]

        return str("{server}{path}/#/?data={ticket}.{scrambler}{onw}".format(
            server=self.guacamoleServer.value,
            path=path,
            ticket=ticket,
            scrambler=scrambler,
            onw=onw,
        ))