Пример #1
0
    def runCommand(self):
        self.parseArgs(
            _("""
Removes association between an existing adminstrative user and hardware or
software profile.
"""))

        swprofile = self.getArgs().swprofile
        hwprofile = self.getArgs().hwprofile

        admin_username = self.getArgs().adminUsername

        if swprofile:
            profile = swprofile

            api = SoftwareProfileWsApi(username=self.getUsername(),
                                       password=self.getPassword(),
                                       baseurl=self.getUrl(),
                                       verify=self._verify)
        else:
            profile = hwprofile

            api = HardwareProfileWsApi(username=self.getUsername(),
                                       password=self.getPassword(),
                                       baseurl=self.getUrl(),
                                       verify=self._verify)

        api.deleteAdmin(profile, admin_username)
Пример #2
0
    def runCommand(self):
        self.parseArgs(_('Create software profile'))

        if self.getArgs().name and self.getArgs().deprecated_name:
            self.getParser().error(
                'argument name: not allowed with argument --name')

        name = self.getArgs().name \
            if self.getArgs().name else self.getArgs().deprecated_name

        # load template if specified with '--template', otherwise build
        # template
        tmpl_dict = {} if not self.getArgs().jsonTemplatePath else \
            self.load_software_profile_template(
                self.getArgs().jsonTemplatePath)

        if name:
            tmpl_dict['name'] = name

        if self.getArgs().description:
            tmpl_dict['description'] = self.getArgs().description

        if self.getArgs().profileType:
            tmpl_dict['type'] = self.getArgs().profileType
        elif 'type' not in tmpl_dict:
            tmpl_dict['type'] = 'compute'

        if self.getArgs().tags:
            tmpl_dict['tags'] = parse_tags(self.getArgs().tags)

        if hasattr(self.getArgs(), 'osInfo'):
            tmpl_dict['os'] = {
                'name': getattr(self.getArgs(), 'osInfo').getName(),
                'version': getattr(self.getArgs(), 'osInfo').getVersion(),
                'arch': getattr(self.getArgs(), 'osInfo').getArch(),
            }

        if self.getArgs().dataRoot:
            tmpl_dict['dataRoot'] = self.getArgs().dataRoot

        if self.getArgs().dataRsync:
            tmpl_dict['dataRsync'] = self.getArgs().dataRsync

        sw_profile_spec = SoftwareProfile.getFromDict(tmpl_dict)

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        # Populate 'settings_dict' from command-line arguments
        settings_dict = {
            'bOsMediaRequired': self.getArgs().bOsMediaRequired,
            'unmanagedProfile': self.getArgs().unmanaged,
        }

        api.createSoftwareProfile(sw_profile_spec, settings_dict)
Пример #3
0
    def runCommand(self):
        self.parseArgs(_('Copy an existing software profile'))

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        api.copySoftwareProfile(self.getArgs().srcSoftwareProfileName,
                                self.getArgs().dstSoftwareProfileName)
Пример #4
0
    def runCommand(self):
        self.parseArgs(_('Return list of software profiles configured in'
                         ' the system'))

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        for sp in api.getSoftwareProfileList(tags=self.getArgs().tags):
            print('%s' % (sp))
Пример #5
0
    def runCommand(self):
        self.parseArgs(usage=_('Displays software profile details'))

        if not self.getArgs().name and not self.getArgs().deprecated_name:
            self.getParser().error(
                'the following arguments are required: NAME')

        if self.getArgs().name and self.getArgs().deprecated_name:
            self.getParser().error(
                'argument name: not allowed with argument --name')

        name = self.getArgs().name \
            if self.getArgs().name else self.getArgs().deprecated_name

        swprofileapi = SoftwareProfileWsApi(username=self.getUsername(),
                                            password=self.getPassword(),
                                            baseurl=self.getUrl(),
                                            verify=self._verify)

        optionDict = {}

        if self.getArgs().getNodes:
            optionDict['nodes'] = True

        if self.getArgs().getPartitions:
            optionDict['partitions'] = True

        if self.getArgs().getComponents:
            optionDict['components'] = True

        if self.getArgs().getAdmins:
            optionDict['admins'] = True

        if self.getArgs().getDataRoot:
            optionDict['dataRoot'] = True

        if self.getArgs().getDataRsync:
            optionDict['dataRsync'] = True

        swprofile = swprofileapi.getSoftwareProfile(name, optionDict)

        if self.getArgs().json:
            print(
                json.dumps({
                    'softwareprofile': swprofile.getCleanDict(),
                },
                           sort_keys=True,
                           indent=4,
                           separators=(',', ': ')))
        elif self.getArgs().xml:
            print(swprofile.getXmlRep())
        else:
            self.__console_output(swprofile)
    def runCommand(self):
        self.parseArgs(
            _("""
Return list of idle software profiles configured on the system.
"""))
        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        for software_profile in api.getSoftwareProfileList():
            if software_profile.getIsIdle():
                print(software_profile.getName())
    def runCommand(self):
        self.parseArgs(_("""
Return list of nodes that are using the specified software profile.
"""))

        software_profile_name = self.getArgs().softwareProfile

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        for node in api.getNodeList(software_profile_name):
            print(str(node))
Пример #8
0
    def runCommand(self):
        self.parseArgs(_("""
Adjust "software uses hardware" attribute on a software  profile.
"""))

        swprofile_name = self.getArgs().swprofile
        hwprofile_name = self.getArgs().hwprofile

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        api.deleteUsableHardwareProfileFromSoftwareProfile(
            hwprofile_name, swprofile_name)
Пример #9
0
    def runCommand(self):
        self.parseArgs(
            _("""
Returns the list of nodes that have the given component enabled. The
result set can be filtered by state and count.
"""))

        state = self.getArgs().state

        if state:
            stateList = state.split(',')

        if self.getArgs().count is not None:
            numNodes = int(self.getArgs().count)
            if numNodes == 0:
                return
        else:
            numNodes = -1

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        optionDict = {}
        optionDict['nodes'] = True

        for sp in api.getSoftwareProfileList():
            comps = api.getEnabledComponentList(sp.getName())
            for comp in comps:
                if comp.getName() == self.getArgs().componentName and \
                   comp.getKit().getName() == self.getArgs().kitName and \
                   comp.getKit().getVersion() == \
                   self.getArgs().kitVersion and \
                   comp.getKit().getIteration() == \
                   self.getArgs().kitIteration:
                    softwareProfile = api.getSoftwareProfile(
                        sp.getName(), optionDict)

                    for node in softwareProfile.getNodes():
                        if state is None or node.getState() in stateList:
                            print(node.getName())

                            numNodes = numNodes - 1

                            if numNodes == 0:
                                return
Пример #10
0
    def runCommand(self):
        self.parseArgs(
            _("""
Multiple software profiles can be mapped to a single hardware profile to
accomodate a consistent software stack across mulitple resource adapters,
for example. All profiles must be mapped in order to be used for active nodes.
"""))

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        try:
            api.addUsableHardwareProfileToSoftwareProfile(
                self.getArgs().hwprofile,
                self.getArgs().swprofile)
        except SoftwareUsesHardwareAlreadyExists:
            pass
Пример #11
0
    def runCommand(self):
        self.parseArgs(_('Removes software profile from system.'))

        if not self.getArgs().name and \
                not self.getArgs().softwareProfileName:
            self.getParser().error(
                'the following arguments are required: NAME')

        if self.getArgs().name and self.getArgs().softwareProfileName:
            self.getParser().error(
                'argument name: not allowed with argument --name')

        name = self.getArgs().name \
            if self.getArgs().name else self.getArgs().softwareProfileName

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        api.deleteSoftwareProfile(name)
Пример #12
0
    def runCommand(self):
        self.parseArgs(
            _("""
Associates an existing adminstrative user with a hardware or software profile.
"""))
        swprofile = self.getArgs().swprofile
        hwprofile = self.getArgs().hwprofile

        if swprofile and hwprofile:
            raise InvalidCliRequest(
                _('Only one of --software-profile and --hardware-profile'
                  ' can be specified.'))

        if not swprofile and not hwprofile:
            raise InvalidCliRequest(
                _('Either --software-profile or --hardware-profile must'
                  ' be specified.'))

        admin_username = self.getArgs().adminUsername

        if admin_username is None:
            raise InvalidCliRequest(_('Missing Admin Username'))

        if swprofile:
            profile = swprofile
            api = SoftwareProfileWsApi(username=self.getUsername(),
                                       password=self.getPassword(),
                                       baseurl=self.getUrl(),
                                       verify=self._verify)
        else:
            profile = hwprofile
            api = HardwareProfileWsApi(username=self.getUsername(),
                                       password=self.getPassword(),
                                       baseurl=self.getUrl(),
                                       verify=self._verify)

        api.addAdmin(profile, admin_username)
Пример #13
0
    def runCommand(self):
        self.parseArgs()

        comp_name = self.getArgs().component

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        results = {}
        for sw_profile in api.getSoftwareProfileList():
            nodes = []

            for component in sw_profile.components:
                if not self.getArgs().kitName or \
                        component.kit.name == self.getArgs().kitName:
                    if comp_name and component.name == comp_name:
                        nodes = [node.name for node in sw_profile.nodes]
                        break

            results[sw_profile.name] = nodes

        print(yaml.safe_dump(results), end=' ')
Пример #14
0
    def runCommand(self):
        self.parseArgs(
            _("""
Display list of components available for software profiles in the system.
"""))

        softwareProfileName = self.__get_software_profile()

        if softwareProfileName:
            # Display all components enabled for software profile

            for c in SoftwareProfileWsApi(
                    username=self.getUsername(),
                    password=self.getPassword(),
                    baseurl=self.getUrl(),
                    verify=self._verify).getEnabledComponentList(
                        softwareProfileName):
                displayComponent(c, c.getKit())

            return

        if self.getArgs().os:
            try:
                name, version, arch = self.getArgs().os.split('-', 3)
            except ValueError:
                self.getParser().error(
                    'Malformed argument to --os. Must be in form of'
                    ' NAME-VERSION-ARCH')

            osinfo = getOsInfo(name, version, arch)
        else:
            osinfo = None

        # Display all components
        for kit in KitWsApi(username=self.getUsername(),
                            password=self.getPassword(),
                            baseurl=self.getUrl(),
                            verify=self._verify).getKitList():
            for c in kit.getComponentList():
                if osinfo and osinfo not in c.getOsInfoList() and \
                        osinfo.getOsFamilyInfo() not in c.getOsFamilyInfoList():
                    # Exclude those components that cannot be enabled on the
                    # specified operating system.
                    continue

                displayComponent(c, kit)
Пример #15
0
def getSoftwareProfileApi(username=None, password=None):
    """
    Creates an object that derives from KitApiInterface
    """

    cm = ConfigManager()

    if username and password or not cm.isDbAvailable():

        from tortuga.wsapi.softwareProfileWsApi import SoftwareProfileWsApi

        api = SoftwareProfileWsApi(username, password)
    else:
        from tortuga.softwareprofile.softwareProfileApi \
            import SoftwareProfileApi

        api = SoftwareProfileApi()

    return api
Пример #16
0
    def runCommand(self):
        self.parseArgs(usage=_("""
Updates software profile in the Tortuga system.
"""))

        if not self.getArgs().name and \
                not self.getArgs().softwareProfileName:
            self.getParser().error(
                'the following arguments are required: NAME'
            )

        if self.getArgs().name and self.getArgs().softwareProfileName:
            self.getParser().error(
                'argument name: not allowed with argument --name'
            )

        name = self.getArgs().name \
            if self.getArgs().name else self.getArgs().softwareProfileName

        api = SoftwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        sp = api.getSoftwareProfile(name, UpdateSoftwareProfileCli.optionDict)

        if self.getArgs().new_name is not None:
            sp.setName(self.getArgs().new_name)

        if self.getArgs().description is not None:
            sp.setDescription(self.getArgs().description)

        if self.getArgs().kernel is not None:
            sp.setKernel(self.getArgs().kernel)

        if self.getArgs().kernelParameters is not None:
            sp.setKernelParams(self.getArgs().kernelParameters)

        if self.getArgs().initrd is not None:
            sp.setInitrd(self.getArgs().initrd)

        if self.getArgs().unlock:
            if self.getArgs().soft_locked is not None:
                raise InvalidCliRequest(
                    '--soft-locked/--hard-locked arguments and --unlock'
                    ' argument are mutually exclusive'
                )

            sp.setLockedState('Unlocked')

        if self.getArgs().soft_locked is not None:
            sp.setLockedState(
                'SoftLocked' if self.getArgs().soft_locked else 'HardLocked')

        if self.getArgs().min_nodes is not None:
            # update min_nodes value
            try:
                if self.getArgs().min_nodes.lower() == 'none':
                    min_nodes = -1
                else:
                    min_nodes = int(self.getArgs().min_nodes)
            except ValueError:
                raise InvalidCliRequest(
                    'Invalid argument value for --min-nodes')

            sp.setMinNodes(min_nodes)
        else:
            min_nodes = sp.getMinNodes()

        if self.getArgs().max_nodes:
            try:
                max_nodes = -1 \
                    if self.getArgs().max_nodes.lower() == 'none' else \
                    int(self.getArgs().max_nodes)
            except ValueError:
                raise InvalidCliRequest(
                    'Invalid argument value for --max-nodes'
                )

            # update maxNodes value
            if max_nodes < min_nodes:
                # do not allow max nodes to be less than min nodes
                raise InvalidCliRequest(
                    'Maximum number of allowed nodes must be greater or equal'
                    ' to the mininum number of required nodes'
                )

            sp.setMaxNodes(max_nodes)

        if self.getArgs().deletePartition is not None:

            out = TortugaObjectList()
            for p in sp.getPartitions():
                for dp in self.getArgs().deletePartition:
                    if dp == p.getName():
                        # Skip over this item..its getting deleted
                        break
                else:
                    # Not a partition we are deleting
                    out.append(p)
            sp.setPartitions(out)

        partitionObject = None
        if self.getArgs().updatePartition:
            if self.getArgs().addPartition:
                raise InvalidCliRequest(
                    _('Must provide only one of --update-partition and'
                      ' --add-partition'))

            for p in sp.getPartitions():
                if p.getName() == self.getArgs().updatePartition:
                    partitionObject = p
                    break
            else:
                raise InvalidCliRequest(
                    _('Cannot update non-existent partition "%s"') % (
                        self.getArgs().updatePartition))

        if self.getArgs().addPartition:
            from tortuga.objects.partition import Partition
            partitionObject = Partition()
            partitionObject.setName(self.getArgs().addPartition)
            sp.getPartitions().append(partitionObject)
            if self.getArgs().device is None or \
                    self.getArgs().fileSystem is None or \
                    self.getArgs().size is None:
                raise InvalidCliRequest(
                    _('--device, --file-system, and --size options required'
                      ' with --add-partition'))

        if self.getArgs().grow:
            if not partitionObject:
                raise InvalidCliRequest(
                    _('The --grow/--no-grow options is only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setGrow(self.getArgs().grow)

        if self.getArgs().maxsize:
            if not partitionObject:
                raise InvalidCliRequest(
                    _('The --max-size option is only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setMaxSize(self.getArgs().maxsize)

        if self.getArgs().device is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('The --device option is only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setDevice(self.getArgs().device)

        if self.getArgs().mountPoint is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--mount-point option only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setMountPoint(self.getArgs().mountPoint)

        if self.getArgs().fileSystem is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('The --file-system option only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setFsType(self.getArgs().fileSystem)

        if self.getArgs().size is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--size option only allowed with --update-partition or'
                      ' --add-partition'))

            partitionObject.setSize(self._parseDiskSize(self.getArgs().size))

        if self.getArgs().options is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--options option only allowed with --update-partition'
                      ' or --add-partition'))

            partitionObject.setOptions(self.getArgs().options)

        if self.getArgs().directAttachment is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--direct-attachment option only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setDirectAttachment(
                self.getArgs().directAttachment)

        if self.getArgs().indirectAttachment is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--indirect-attachment option only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setIndirectAttachment(
                self.getArgs().indirectAttachment)

        if self.getArgs().diskSize is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--disk-size option only allowed with'
                      ' --update-partition or --add-partition'))

            try:
                partitionObject.setDiskSize(
                    self._parseDiskSize(self.getArgs().diskSize))
            except ValueError:
                raise InvalidCliRequest(_('Invalid --disk-size argument'))

        if self.getArgs().sanVolume is not None:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--san-volume option only allowed with'
                      ' --update-partition or --add-partition'))

            partitionObject.setSanVolume(self.getArgs().sanVolume)

        if self.getArgs().preserve is None:
            if self.getArgs().addPartition is not None:
                raise InvalidCliRequest(
                    _('--preserve or --no-preserve must be specified when'
                      ' adding a new partition.'))
        else:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--preserve and --no-preserve options are only allowed'
                      ' with --update-partition or --add-partition'))

            partitionObject.setPreserve(self.getArgs().preserve)

        if self.getArgs().bootLoader is None:
            if self.getArgs().addPartition is not None:
                raise InvalidCliRequest(
                    _('--boot-loader or --no-boot-loader must be specified'
                      ' when adding a new partition.'))
        else:
            if partitionObject is None:
                raise InvalidCliRequest(
                    _('--boot-loader and --no-boot-loader options only'
                      ' allowed with --update-partition or --add-partition'))

            partitionObject.setBootLoader(self.getArgs().bootLoader)

        if self.getArgs().tags:
            tags = sp.getTags()
            tags.update(parse_tags(self.getArgs().tags))
            sp.setTags(tags)
            print(tags)  # DEBUG

        if self.getArgs().remove_tags:
            tags = sp.getTags()
            for string in self.getArgs().remove_tags:
                for tag_name in string.split(','):
                    if tag_name in tags.keys():
                        tags.pop(tag_name)
            sp.setTags(tags)
            print(tags)  # DEBUG

        if self.getArgs().dataRoot is not None:
            sp.setDataRoot(self.getArgs().dataRoot)

        if self.getArgs().dataRsync is not None:
            sp.setDataRsync(self.getArgs().dataRsync)

        api.updateSoftwareProfile(sp)
Пример #17
0
    def parseArgs(self, usage=None):
        excl_option_group = self.getParser().add_mutually_exclusive_group(
            required=True)

        excl_option_group.add_argument('--software-profile',
                                       dest='softwareProfileName',
                                       metavar='NAME',
                                       help=_('Software profile to act on'))

        excl_option_group.add_argument(
            '-p',
            dest='applyToInstaller',
            action='store_true',
            default=False,
            help=_('Perform action on Tortuga installer software profile'))

        self.addOption('--kit-name',
                       dest='kitName',
                       metavar='NAME',
                       help=_('kit name'))

        self.addOption('--kit-version',
                       dest='kitVersion',
                       metavar='VERSION',
                       help=_('kit version'))

        self.addOption('--kit-iteration',
                       dest='kitIteration',
                       metavar='ITERATION',
                       help=_('kit iteration'))

        self.addOption('--comp-name',
                       dest='compName',
                       metavar='NAME',
                       help=_('component name'))

        self.addOption('--comp-version',
                       dest='compVersion',
                       metavar='VERSION',
                       help=_('component version'))

        self.addOption('--no-sync',
                       dest='sync',
                       action='store_false',
                       default=True,
                       help=argparse.SUPPRESS)

        self.addOption('args', nargs='*')

        super().parseArgs(usage=usage)

        if self.getArgs().args:
            if len(self.getArgs().args) == 1 and \
                    '-' not in self.getArgs().args[0]:
                # The first argument is assumed to be the component name.
                self.component_name = self.getArgs().args[0]

                self.kit_name = self.getArgs().kitName
                self.kit_version = self.getArgs().kitVersion
                self.kit_iteration = self.getArgs().kitIteration
            else:
                # Get given Kit information
                kit_name = None
                if len(self.getArgs().args) >= 1:
                    kit_name = self.getArgs().args[0]

                # get installed kit name/version/iteration using name only
                self.kit_name, self.kit_version, self.kit_iteration = \
                    self.getKitNameVersionIteration(kit_name)

                # Get given Component information
                if len(self.getArgs().args) >= 2:
                    vals = self.getArgs().args[1].rsplit('-', 1)
                    self.component_name = vals[0]

                if not self.component_name:
                    self.usage(_('Missing component name'))
        else:
            # copy args from command-line
            self.kit_name = self.getArgs().kitName
            self.kit_version = self.getArgs().kitVersion
            self.kit_iteration = self.getArgs().getIteration
            self.component_name = self.getArgs().compName

        # Get the given software profile information
        self.software_profile_name = self.__get_software_profile_name()

        self.software_profile_api = SoftwareProfileWsApi(
            username=self.getUsername(),
            password=self.getPassword(),
            baseurl=self.getUrl(),
            verify=self._verify)
Пример #18
0
    def runCommand(self):
        self.parseArgs()

        if not self.getArgs().name and \
                not self.getArgs().hardwareProfileName:
            self.getParser().error(
                'the following arguments are required: NAME')

        if self.getArgs().name and self.getArgs().hardwareProfileName:
            self.getParser().error(
                'argument name: not allowed with argument --name')

        name = self.getArgs().name \
            if self.getArgs().name else self.getArgs().hardwareProfileName

        api = HardwareProfileWsApi(username=self.getUsername(),
                                   password=self.getPassword(),
                                   baseurl=self.getUrl(),
                                   verify=self._verify)

        spApi = SoftwareProfileWsApi(username=self.getUsername(),
                                     password=self.getPassword(),
                                     baseurl=self.getUrl(),
                                     verify=self._verify)

        nodeApi = NodeWsApi(username=self.getUsername(),
                            password=self.getPassword(),
                            baseurl=self.getUrl(),
                            verify=self._verify)

        hp = api.getHardwareProfile(name, UpdateHardwareProfileCli.optionDict)

        if self.getArgs().newName is not None:
            hp.setName(self.getArgs().newName)

        if self.getArgs().description is not None:
            hp.setDescription(self.getArgs().description)

        if self.getArgs().nameFormat is not None:
            hp.setNameFormat(self.getArgs().nameFormat)

        if self.getArgs().kernel is not None:
            hp.setKernel(self.getArgs().kernel)

        if self.getArgs().kernelParameters is not None:
            hp.setKernelParams(self.getArgs().kernelParameters)

        if self.getArgs().initrd is not None:
            hp.setInitrd(self.getArgs().initrd)

        if self.getArgs().soAllowed is not None:
            if self.getArgs().soAllowed.lower() == _('true'):
                hp.setSoftwareOverrideAllowed(True)
            elif self.getArgs().soAllowed.lower() == _('false'):
                hp.setSoftwareOverrideAllowed(False)
            else:
                raise InvalidCliRequest(
                    _('--software-override-allowed must be either "true" or'
                      ' "false".'))

        if self.getArgs().idleProfile is not None and \
           self.getArgs().bUnsetIdleProfile:
            raise InvalidCliRequest(
                _('Conflicting options --idle-software-profile and'
                  ' --unset-idle-software-profile'))

        if self.getArgs().idleProfile is not None:
            sp = spApi.getSoftwareProfile(self.getArgs().idleProfile)

            hp.setIdleSoftwareProfileId(sp.getId())

        if self.getArgs().bUnsetIdleProfile:
            hp.setIdleSoftwareProfileId(None)

        if self.getArgs().location is not None:
            hp.setLocation(self.getArgs().location)

        if self.getArgs().localBootParameters is not None:
            hp.setLocalBootParams(self.getArgs().localBootParameters)

        if self.getArgs().cost is not None:
            hp.setCost(self.getArgs().cost)

        if self.getArgs().resourceAdapter:
            resourceAdapter = ResourceAdapter(
                name=self.getArgs().resourceAdapter)
            hp.setResourceAdapter(resourceAdapter)

        if self.getArgs().default_adapter_config:
            hp.setDefaultResourceAdapterConfig(
                self.getArgs().default_adapter_config)

        if self.getArgs().deletePNic is not None:
            out = TortugaObjectList()

            for nic in hp.getProvisioningNics():
                for dnic in self.getArgs().deletePNic:
                    if dnic == nic.getIp():
                        # Skip over this item..its getting deleted
                        break
                else:
                    # Not a NIC we are deleting
                    out.append(nic)

            hp.setProvisioningNics(out)

        if self.getArgs().addPNic is not None:
            for nicIp in self.getArgs().addPNic:
                nicsNode = nodeApi.getNodeByIp(nicIp)

                if nicsNode is not None:
                    for nic in nicsNode.getNics():
                        if nic.getIp() == nicIp:
                            hp.getProvisioningNics().append(nic)
                            break

        if self.getArgs().deleteNetwork is not None:
            # Make sure we actually delete a network
            out = TortugaObjectList()
            out.extend(hp.getNetworks())

            for netstring in self.getArgs().deleteNetwork:
                try:
                    dnet, dmask, ddev = netstring.split('/')
                except ValueError:
                    raise InvalidCliRequest(
                        _('Incorrect input format for --delete-network'
                          ' ("address/mask/device")'))

                for network in hp.getNetworks():
                    if dnet == network.getAddress() and \
                       dmask == network.getNetmask() and \
                       ddev == network.getNetworkDevice().getName():
                        # Skip over this item..its getting deleted
                        for n in out:
                            if n.getId() == network.getId():
                                out.remove(n)
                                break

                        break
                else:
                    # Not a NIC we are deleting
                    print('Ignoring deletion of non-existent network:'
                          ' %s/%s/%s' % (dnet, dmask, ddev))

            hp.setNetworks(out)

        if self.getArgs().addNetwork:
            for netstring in self.getArgs().addNetwork:
                try:
                    anet, amask, adev = netstring.split('/')
                except ValueError:
                    raise InvalidCliRequest(
                        _('Incorrect input format for --add-network'
                          ' ("address/mask/device")'))

                network = Network()
                networkDevice = NetworkDevice()
                networkDevice.setName(adev)
                network.setAddress(anet)
                network.setNetmask(amask)
                network.setNetworkDevice(networkDevice)
                hp.getNetworks().append(network)

        if self.getArgs().tags:
            tags = hp.getTags()
            tags.update(parse_tags(self.getArgs().tags))
            hp.setTags(tags)

        if self.getArgs().remove_tags:
            tags = hp.getTags()
            for string in self.getArgs().remove_tags:
                for tag_name in string.split(','):
                    if tag_name in tags.keys():
                        tags.pop(tag_name)
            hp.setTags(tags)

        api.updateHardwareProfile(hp)